Merge branch 'krahets:master' into master

This commit is contained in:
Zero 2023-01-16 16:47:13 +08:00 committed by GitHub
commit 23f2bf8c67
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
62 changed files with 723 additions and 167 deletions

15
.gitattributes vendored Normal file
View File

@ -0,0 +1,15 @@
*.java linguist-language=Java
*.cs linguist-language=Java
*.py linguist-language=Python
*.cpp linguist-language=C++
*.c linguist-language=C++
*.go linguist-language=Go
*.js linguist-language=JavaScript
*.ts linguist-language=JavaScript
*.swift linguist-language=Swift
*.zig linguist-language=Other
*.rs linguist-language=Other
*.html linguist-detectable=false
*.css linguist-detectable=false

View File

@ -23,6 +23,8 @@ int* extend(int* nums, int size, int enlarge) {
for (int i = 0; i < size; i++) {
res[i] = nums[i];
}
// 释放内存
delete[] nums;
// 返回扩展后的新数组
return res;
}
@ -82,10 +84,7 @@ int main() {
/* 长度扩展 */
int enlarge = 3;
int* res = extend(nums, size, enlarge);
int* temp = nums;
nums = res;
delete[] temp;
nums = extend(nums, size, enlarge);
size += enlarge;
cout << "将数组长度扩展至 8 ,得到 nums = ";
PrintUtil::printArray(nums, size);
@ -107,5 +106,9 @@ int main() {
int index = find(nums, size, 3);
cout << "在 nums 中查找元素 3 ,得到索引 = " << index << endl;
// 释放内存
delete[] arr;
delete[] nums;
return 0;
}

View File

@ -83,5 +83,8 @@ int main() {
int index = find(n0, 2);
cout << "链表中值为 2 的结点的索引 = " << index << endl;
// 释放内存
freeMemoryLinkedList(n0);
return 0;
}

View File

@ -20,6 +20,11 @@ public:
nums = new int[numsCapacity];
}
/* 析构函数 */
~MyList() {
delete[] nums;
}
/* 获取列表长度(即当前元素数量)*/
int size() {
return numsSize;
@ -90,14 +95,14 @@ public:
void extendCapacity() {
// 新建一个长度为 size * extendRatio 的数组,并将原数组拷贝到新数组
int newCapacity = capacity() * extendRatio;
int* extend = new int[newCapacity];
int* tmp = nums;
nums = new int[newCapacity];
// 将原数组中的所有元素复制到新数组
for (int i = 0; i < size(); i++) {
extend[i] = nums[i];
nums[i] = tmp[i];
}
int* temp = nums;
nums = extend;
delete[] temp;
// 释放内存
delete[] tmp;
numsCapacity = newCapacity;
}
@ -160,5 +165,8 @@ int main() {
PrintUtil::printVector(vec);
cout << "容量 = " << list->capacity() << " ,长度 = " << list->size() << endl;
// 释放内存
delete list;
return 0;
}

View File

@ -56,5 +56,9 @@ int main() {
cout << "方法二 res = ";
PrintUtil::printVector(res);
// 释放内存
delete slt1;
delete slt2;
return 0;
}

View File

@ -18,7 +18,7 @@ void constant(int n) {
const int a = 0;
int b = 0;
vector<int> nums(10000);
ListNode* node = new ListNode(0);
ListNode node(0);
// 循环中的变量占用 O(1) 空间
for (int i = 0; i < n; i++) {
int c = 0;
@ -34,9 +34,9 @@ void linear(int n) {
// 长度为 n 的数组占用 O(n) 空间
vector<int> nums(n);
// 长度为 n 的列表占用 O(n) 空间
vector<ListNode*> nodes;
vector<ListNode> nodes;
for (int i = 0; i < n; i++) {
nodes.push_back(new ListNode(i));
nodes.push_back(ListNode(i));
}
// 长度为 n 的哈希表占用 O(n) 空间
unordered_map<int, string> map;
@ -98,5 +98,8 @@ int main() {
TreeNode* root = buildTree(n);
PrintUtil::printTree(root);
// 释放内存
freeMemoryTree(root);
return 0;
}

View File

@ -59,7 +59,7 @@ private:
static int medianThree(vector<int>& nums, int left, int mid, int right) {
// 使用了异或操作来简化代码
// 异或规则为 0 ^ 0 = 1 ^ 1 = 0, 0 ^ 1 = 1 ^ 0 = 1
if ((nums[left] > nums[mid]) ^ (nums[left] > nums[right]))
if ((nums[left] < nums[mid]) ^ (nums[left] < nums[right]))
return left;
else if ((nums[mid] < nums[left]) ^ (nums[mid] < nums[right]))
return mid;

View File

@ -21,6 +21,10 @@ public:
nums = new int[capacity];
}
~ArrayQueue() {
delete[] nums;
}
/* 获取队列的容量 */
int capacity() {
return cap;
@ -117,5 +121,8 @@ int main() {
PrintUtil::printVector(queue->toVector());
}
// 释放内存
delete queue;
return 0;
}

View File

@ -78,5 +78,8 @@ int main() {
bool empty = stack->empty();
cout << "栈是否为空 = " << empty << endl;
// 释放内存
delete stack;
return 0;
}

View File

@ -19,6 +19,11 @@ public:
queSize = 0;
}
~LinkedListQueue() {
delete front;
delete rear;
}
/* 获取队列的长度 */
int size() {
return queSize;
@ -108,5 +113,8 @@ int main() {
bool empty = queue->empty();
cout << "队列是否为空 = " << empty << endl;
// 释放内存
delete queue;
return 0;
}

View File

@ -18,6 +18,10 @@ public:
stkSize = 0;
}
~LinkedListStack() {
freeMemoryLinkedList(stackTop);
}
/* 获取栈的长度 */
int size() {
return stkSize;
@ -97,5 +101,8 @@ int main() {
bool empty = stack->empty();
cout << "栈是否为空 = " << empty << endl;
// 释放内存
delete stack;
return 0;
}

View File

@ -17,6 +17,10 @@ public:
root = buildTree(nums, 0, nums.size() - 1); // 构建二叉搜索树
}
~BinarySearchTree() {
freeMemoryTree(root);
}
/* 获取二叉树根结点 */
TreeNode* getRoot() {
return root;
@ -82,9 +86,9 @@ public:
// 找到待删除结点,跳出循环
if (cur->val == num) break;
pre = cur;
// 待删除结点在 root 的右子树中
// 待删除结点在 cur 的右子树中
if (cur->val < num) cur = cur->right;
// 待删除结点在 root 的左子树中
// 待删除结点在 cur 的左子树中
else cur = cur->left;
}
// 若无待删除结点,则直接返回
@ -152,5 +156,8 @@ int main() {
cout << endl << "删除结点 4 后,二叉树为\n" << endl;
PrintUtil::printTree(bst->getRoot());
// 释放内存
delete bst;
return 0;
}

View File

@ -37,5 +37,8 @@ int main() {
cout << endl << "删除结点 P 后\n" << endl;
PrintUtil::printTree(n1);
// 释放内存
freeMemoryTree(n1);
return 0;
}

View File

@ -48,3 +48,18 @@ ListNode* getListNode(ListNode *head, int val) {
}
return head;
}
/**
* @brief Free the memory allocated to a linked list
*
* @param cur
*/
void freeMemoryLinkedList(ListNode *cur) {
// 释放内存
ListNode *pre;
while (cur != nullptr) {
pre = cur;
cur = cur->next;
delete pre;
}
}

View File

@ -68,3 +68,16 @@ TreeNode *getTreeNode(TreeNode *root, int val) {
TreeNode *right = getTreeNode(root->right, val);
return left != nullptr ? left : right;
}
/**
* @brief Free the memory allocated to a tree
*
* @param root
*/
void freeMemoryTree(TreeNode *root) {
if (root == nullptr) return;
freeMemoryTree(root->left);
freeMemoryTree(root->right);
// 释放内存
delete root;
}

View File

@ -65,7 +65,7 @@ namespace hello_algo.chapter_sorting
{
// 使用了异或操作来简化代码
// 异或规则为 0 ^ 0 = 1 ^ 1 = 0, 0 ^ 1 = 1 ^ 0 = 1
if ((nums[left] > nums[mid]) ^ (nums[left] > nums[right]))
if ((nums[left] < nums[mid]) ^ (nums[left] < nums[right]))
return left;
else if ((nums[mid] < nums[left]) ^ (nums[mid] < nums[right]))
return mid;

View File

@ -94,9 +94,9 @@ namespace hello_algo.chapter_tree
// 找到待删除结点跳出循环
if (cur.val == num) break;
pre = cur;
// 待删除结点在 root 的右子树中
// 待删除结点在 cur 的右子树中
if (cur.val < num) cur = cur.right;
// 待删除结点在 root 的左子树中
// 待删除结点在 cur 的左子树中
else cur = cur.left;
}
// 若无待删除结点则直接返回

View File

@ -98,6 +98,7 @@ func (h *maxHeap) poll() any {
// 判空处理
if h.isEmpty() {
fmt.Println("error")
return nil
}
// 交换根结点与最右叶结点(即交换首元素与尾元素)
h.swap(0, h.size()-1)

View File

@ -47,9 +47,11 @@ func (q *quickSort) quickSort(nums []int, left, right int) {
/* 选取三个元素的中位数 */
func (q *quickSortMedian) medianThree(nums []int, left, mid, right int) int {
if (nums[left] > nums[mid]) != (nums[left] > nums[right]) {
// 使用了异或操作来简化代码(!= 在这里起到异或的作用)
// 异或规则为 0 ^ 0 = 1 ^ 1 = 0, 0 ^ 1 = 1 ^ 0 = 1
if (nums[left] < nums[mid]) != (nums[left] < nums[right]) {
return left
} else if (nums[mid] < nums[left]) != (nums[mid] > nums[right]) {
} else if (nums[mid] < nums[left]) != (nums[mid] < nums[right]) {
return mid
}
return right

View File

@ -1,5 +1,5 @@
/**
* File: my_heap.java
* File: heap.java
* Created Time: 2023-01-07
* Author: Krahets (krahets@163.com)
*/

View File

@ -58,7 +58,7 @@ class QuickSortMedian {
static int medianThree(int[] nums, int left, int mid, int right) {
// 使用了异或操作来简化代码
// 异或规则为 0 ^ 0 = 1 ^ 1 = 0, 0 ^ 1 = 1 ^ 0 = 1
if ((nums[left] > nums[mid]) ^ (nums[left] > nums[right]))
if ((nums[left] < nums[mid]) ^ (nums[left] < nums[right]))
return left;
else if ((nums[mid] < nums[left]) ^ (nums[mid] < nums[right]))
return mid;

View File

@ -83,9 +83,9 @@ class BinarySearchTree {
// 找到待删除结点跳出循环
if (cur.val == num) break;
pre = cur;
// 待删除结点在 root 的右子树中
// 待删除结点在 cur 的右子树中
if (cur.val < num) cur = cur.right;
// 待删除结点在 root 的左子树中
// 待删除结点在 cur 的左子树中
else cur = cur.left;
}
// 若无待删除结点则直接返回

View File

@ -11,10 +11,10 @@ function bubbleSort(nums) {
// 内循环:冒泡操作
for (let j = 0; j < i; j++) {
if (nums[j] > nums[j + 1]) {
// 交换 nums[j] 与 nums[j + 1]
let tmp = nums[j];
nums[j] = nums[j + 1];
nums[j + 1] = tmp;
// 交换 nums[j] 与 nums[j + 1]
let tmp = nums[j];
nums[j] = nums[j + 1];
nums[j + 1] = tmp;
}
}
}
@ -40,10 +40,10 @@ function bubbleSortWithFlag(nums) {
}
/* Driver Code */
var nums = [4, 1, 3, 1, 5, 2]
bubbleSort(nums)
console.log("排序后数组 nums =", nums)
const nums = [4, 1, 3, 1, 5, 2];
bubbleSort(nums);
console.log("排序后数组 nums =", nums);
var nums1 = [4, 1, 3, 1, 5, 2]
bubbleSortWithFlag(nums1)
console.log("排序后数组 nums =", nums1)
const nums1 = [4, 1, 3, 1, 5, 2];
bubbleSortWithFlag(nums1);
console.log("排序后数组 nums =", nums1);

View File

@ -19,6 +19,6 @@ function insertionSort(nums) {
}
/* Driver Code */
var nums = [4, 1, 3, 1, 5, 2]
insertionSort(nums)
console.log("排序后数组 nums =", nums)
const nums = [4, 1, 3, 1, 5, 2];
insertionSort(nums);
console.log('排序后数组 nums =', nums);

View File

@ -5,10 +5,10 @@
*/
/**
* 合并左子数组和右子数组
* 左子数组区间 [left, mid]
* 右子数组区间 [mid + 1, right]
*/
* 合并左子数组和右子数组
* 左子数组区间 [left, mid]
* 右子数组区间 [mid + 1, right]
*/
function merge(nums, left, mid, right) {
// 初始化辅助数组
let tmp = nums.slice(left, right + 1);
@ -46,6 +46,6 @@ function mergeSort(nums, left, right) {
}
/* Driver Code */
var nums = [ 7, 3, 2, 6, 0, 1, 5, 4 ]
const nums = [ 7, 3, 2, 6, 0, 1, 5, 4 ]
mergeSort(nums, 0, nums.length - 1)
console.log("归并排序完成后 nums =", nums)
console.log('归并排序完成后 nums =', nums)

View File

@ -8,38 +8,38 @@
class QuickSort {
/* 元素交换 */
swap(nums, i, j) {
let tmp = nums[i]
nums[i] = nums[j]
nums[j] = tmp
let tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
/* 哨兵划分 */
partition(nums, left, right){
partition(nums, left, right) {
// 以 nums[left] 作为基准数
let i = left, j = right
while(i < j){
while(i < j && nums[j] >= nums[left]){
j -= 1 // 从右向左找首个小于基准数的元素
let i = left, j = right;
while (i < j) {
while (i < j && nums[j] >= nums[left]) {
j -= 1; // 从右向左找首个小于基准数的元素
}
while(i < j && nums[i] <= nums[left]){
i += 1 // 从左向右找首个大于基准数的元素
while (i < j && nums[i] <= nums[left]) {
i += 1; // 从左向右找首个大于基准数的元素
}
// 元素交换
this.swap(nums, i, j) // 交换这两个元素
this.swap(nums, i, j); // 交换这两个元素
}
this.swap(nums, i, left) // 将基准数交换至两子数组的分界线
return i // 返回基准数的索引
this.swap(nums, i, left); // 将基准数交换至两子数组的分界线
return i; // 返回基准数的索引
}
/* 快速排序 */
quickSort(nums, left, right){
quickSort(nums, left, right) {
// 子数组长度为 1 时终止递归
if(left >= right) return
if (left >= right) return;
// 哨兵划分
const pivot = this.partition(nums, left, right)
const pivot = this.partition(nums, left, right);
// 递归左子数组、右子数组
this.quickSort(nums, left, pivot - 1)
this.quickSort(nums, pivot + 1, right)
this.quickSort(nums, left, pivot - 1);
this.quickSort(nums, pivot + 1, right);
}
}
@ -47,21 +47,18 @@ class QuickSort {
class QuickSortMedian {
/* 元素交换 */
swap(nums, i, j) {
let tmp = nums[i]
nums[i] = nums[j]
nums[j] = tmp
let tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
/* 选取三个元素的中位数 */
medianThree(nums, left, mid, right) {
// 使用了异或操作来简化代码
// 异或规则为 0 ^ 0 = 1 ^ 1 = 0, 0 ^ 1 = 1 ^ 0 = 1
if ((nums[left] > nums[mid]) ^ (nums[left] > nums[right]))
return left;
else if ((nums[mid] < nums[left]) ^ (nums[mid] < nums[right]))
return mid;
else
return right;
if ((nums[left] < nums[mid]) ^ (nums[left] < nums[right])) return left;
else if ((nums[mid] < nums[left]) ^ (nums[mid] < nums[right])) return mid;
else return right;
}
/* 哨兵划分(三数取中值) */
@ -73,14 +70,12 @@ class QuickSortMedian {
// 以 nums[left] 作为基准数
let i = left, j = right;
while (i < j) {
while (i < j && nums[j] >= nums[left])
j--; // 从右向左找首个小于基准数的元素
while (i < j && nums[i] <= nums[left])
i++; // 从左向右找首个大于基准数的元素
while (i < j && nums[j] >= nums[left]) j--; // 从右向左找首个小于基准数的元素
while (i < j && nums[i] <= nums[left]) i++; // 从左向右找首个大于基准数的元素
this.swap(nums, i, j); // 交换这两个元素
}
this.swap(nums, i, left); // 将基准数交换至两子数组的分界线
return i; // 返回基准数的索引
this.swap(nums, i, left); // 将基准数交换至两子数组的分界线
return i; // 返回基准数的索引
}
/* 快速排序 */
@ -99,9 +94,9 @@ class QuickSortMedian {
class QuickSortTailCall {
/* 元素交换 */
swap(nums, i, j) {
let tmp = nums[i]
nums[i] = nums[j]
nums[j] = tmp
let tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
/* 哨兵划分 */
@ -109,13 +104,11 @@ class QuickSortTailCall {
// 以 nums[left] 作为基准数
let i = left, j = right;
while (i < j) {
while (i < j && nums[j] >= nums[left])
j--; // 从右向左找首个小于基准数的元素
while (i < j && nums[i] <= nums[left])
i++; // 从左向右找首个大于基准数的元素
while (i < j && nums[j] >= nums[left]) j--; // 从右向左找首个小于基准数的元素
while (i < j && nums[i] <= nums[left]) i++; // 从左向右找首个大于基准数的元素
this.swap(nums, i, j); // 交换这两个元素
}
this.swap(nums, i, left); // 将基准数交换至两子数组的分界线
this.swap(nums, i, left); // 将基准数交换至两子数组的分界线
return i; // 返回基准数的索引
}
@ -127,8 +120,8 @@ class QuickSortTailCall {
let pivot = this.partition(nums, left, right);
// 对两个子数组中较短的那个执行快排
if (pivot - left < right - pivot) {
this.quickSort(nums, left, pivot - 1); // 递归排序左子数组
left = pivot + 1; // 剩余待排序区间为 [pivot + 1, right]
this.quickSort(nums, left, pivot - 1); // 递归排序左子数组
left = pivot + 1; // 剩余待排序区间为 [pivot + 1, right]
} else {
this.quickSort(nums, pivot + 1, right); // 递归排序右子数组
right = pivot - 1; // 剩余待排序区间为 [left, pivot - 1]
@ -139,19 +132,19 @@ class QuickSortTailCall {
/* Driver Code */
/* 快速排序 */
var nums = [4, 1, 3, 1, 5, 2]
var quickSort = new QuickSort()
quickSort.quickSort(nums, 0, nums.length - 1)
console.log("快速排序完成后 nums =", nums)
const nums = [4, 1, 3, 1, 5, 2];
const quickSort = new QuickSort();
quickSort.quickSort(nums, 0, nums.length - 1);
console.log('快速排序完成后 nums =', nums);
/* 快速排序(中位基准数优化) */
nums1 = [4, 1, 3, 1, 5,2]
var quickSortMedian = new QuickSort()
quickSortMedian.quickSort(nums1, 0, nums1.length - 1)
console.log("快速排序(中位基准数优化)完成后 nums =", nums1)
const nums1 = [4, 1, 3, 1, 5, 2];
const quickSortMedian = new QuickSort();
quickSortMedian.quickSort(nums1, 0, nums1.length - 1);
console.log('快速排序(中位基准数优化)完成后 nums =', nums1);
/* 快速排序(尾递归优化) */
nums2 = [4, 1, 3, 1, 5, 2]
var quickSortTailCall = new QuickSort()
quickSortTailCall.quickSort(nums2, 0, nums2.length - 1)
console.log("快速排序(尾递归优化)完成后 nums =", nums2)
const nums2 = [4, 1, 3, 1, 5, 2];
const quickSortTailCall = new QuickSort();
quickSortTailCall.quickSort(nums2, 0, nums2.length - 1);
console.log('快速排序(尾递归优化)完成后 nums =', nums2);

View File

@ -80,9 +80,9 @@ function remove(num) {
// 找到待删除结点,跳出循环
if (cur.val === num) break;
pre = cur;
// 待删除结点在 root 的右子树中
// 待删除结点在 cur 的右子树中
if (cur.val < num) cur = cur.right;
// 待删除结点在 root 的左子树中
// 待删除结点在 cur 的左子树中
else cur = cur.left;
}
// 若无待删除结点,则直接返回

View File

@ -42,7 +42,7 @@ class QuickSortMedian:
def median_three(self, nums, left, mid, right):
# 使用了异或操作来简化代码
# 异或规则为 0 ^ 0 = 1 ^ 1 = 0, 0 ^ 1 = 1 ^ 0 = 1
if (nums[left] > nums[mid]) ^ (nums[left] > nums[right]):
if (nums[left] < nums[mid]) ^ (nums[left] < nums[right]):
return left
elif (nums[mid] < nums[left]) ^ (nums[mid] > nums[right]):
return mid

View File

@ -94,9 +94,9 @@ class BinarySearchTree:
if cur.val == num:
break
pre = cur
if cur.val < num: # 待删除结点在 root 的右子树中
if cur.val < num: # 待删除结点在 cur 的右子树中
cur = cur.right
else: # 待删除结点在 root 的左子树中
else: # 待删除结点在 cur 的左子树中
cur = cur.left
# 若无待删除结点,则直接返回

View File

@ -19,6 +19,7 @@ let package = Package(
.executable(name: "queue", targets: ["queue"]),
.executable(name: "linkedlist_queue", targets: ["linkedlist_queue"]),
.executable(name: "array_queue", targets: ["array_queue"]),
.executable(name: "deque", targets: ["deque"]),
],
targets: [
.target(name: "utils", path: "utils"),
@ -36,5 +37,6 @@ let package = Package(
.executableTarget(name: "queue", path: "chapter_stack_and_queue", sources: ["queue.swift"]),
.executableTarget(name: "linkedlist_queue", dependencies: ["utils"], path: "chapter_stack_and_queue", sources: ["linkedlist_queue.swift"]),
.executableTarget(name: "array_queue", path: "chapter_stack_and_queue", sources: ["array_queue.swift"]),
.executableTarget(name: "deque", path: "chapter_stack_and_queue", sources: ["deque.swift"]),
]
)

View File

@ -0,0 +1,44 @@
/**
* File: deque.swift
* Created Time: 2023-01-14
* Author: nuomi1 (nuomi1@qq.com)
*/
@main
enum Deque {
/* Driver Code */
static func main() {
/* */
// Swift Array 使
var deque: [Int] = []
/* */
deque.append(2)
deque.append(5)
deque.append(4)
deque.insert(3, at: 0)
deque.insert(1, at: 0)
print("双向队列 deque = \(deque)")
/* 访 */
let peekFirst = deque.first!
print("队首元素 peekFirst = \(peekFirst)")
let peekLast = deque.last!
print("队尾元素 peekLast = \(peekLast)")
/* */
// 使 Array pollFirst O(n)
let pollFirst = deque.removeFirst()
print("队首出队元素 pollFirst = \(pollFirst),队首出队后 deque = \(deque)")
let pollLast = deque.removeLast()
print("队尾出队元素 pollLast = \(pollLast),队尾出队后 deque = \(deque)")
/* */
let size = deque.count
print("双向队列长度 size = \(size)")
/* */
let isEmpty = deque.isEmpty
print("双向队列是否为空 = \(isEmpty)")
}
}

View File

@ -25,6 +25,7 @@ enum Queue {
print("队首元素 peek = \(peek)")
/* */
// 使 Array poll O(n)
let pool = queue.removeFirst()
print("出队元素 poll = \(pool),出队后 queue = \(queue)")

View File

@ -23,10 +23,10 @@ function merge(nums: number[], left: number, mid: number, right: number): void {
// 若“左子数组已全部合并完”,则选取右子数组元素,并且 j++
if (i > leftEnd) {
nums[k] = tmp[j++];
// 否则,若“右子数组已全部合并完”或“左子数组元素 <= 右子数组元素”,则选取左子数组元素,并且 i++
// 否则,若“右子数组已全部合并完”或“左子数组元素 <= 右子数组元素”,则选取左子数组元素,并且 i++
} else if (j > rightEnd || tmp[i] <= tmp[j]) {
nums[k] = tmp[i++];
// 否则,若“左右子数组都未全部合并完”且“左子数组元素 > 右子数组元素”,则选取右子数组元素,并且 j++
// 否则,若“左右子数组都未全部合并完”且“左子数组元素 > 右子数组元素”,则选取右子数组元素,并且 j++
} else {
nums[k] = tmp[j++];
}

View File

@ -58,7 +58,7 @@ class QuickSortMedian {
medianThree(nums: number[], left: number, mid: number, right: number): number {
// 使用了异或操作来简化代码
// 异或规则为 0 ^ 0 = 1 ^ 1 = 0, 0 ^ 1 = 1 ^ 0 = 1
if (Number(nums[left] > nums[mid]) ^ Number(nums[left] > nums[right])) {
if (Number(nums[left] < nums[mid]) ^ Number(nums[left] < nums[right])) {
return left;
} else if (Number(nums[mid] < nums[left]) ^ Number(nums[mid] < nums[right])) {
return mid;

View File

@ -97,9 +97,9 @@ function remove(num: number): TreeNode | null {
}
pre = cur;
if (cur.val < num) {
cur = cur.right as TreeNode; // 待删除结点在 root 的右子树中
cur = cur.right as TreeNode; // 待删除结点在 cur 的右子树中
} else {
cur = cur.left as TreeNode; // 待删除结点在 root 的左子树中
cur = cur.left as TreeNode; // 待删除结点在 cur 的左子树中
}
}
// 若无待删除结点,则直接返回

View File

@ -160,6 +160,62 @@ pub fn build(b: *std.build.Builder) void {
const run_step_array_stack = b.step("run_array_stack", "Run array_stack");
run_step_array_stack.dependOn(&run_cmd_array_stack.step);
// Section: "Hash Map"
// Source File: "chapter_hashing/hash_map.zig"
// Run Command: zig build run_hash_map
const exe_hash_map = b.addExecutable("hash_map", "chapter_hashing/hash_map.zig");
exe_hash_map.addPackagePath("include", "include/include.zig");
exe_hash_map.setTarget(target);
exe_hash_map.setBuildMode(mode);
exe_hash_map.install();
const run_cmd_hash_map = exe_hash_map.run();
run_cmd_hash_map.step.dependOn(b.getInstallStep());
if (b.args) |args| run_cmd_hash_map.addArgs(args);
const run_step_hash_map= b.step("run_hash_map", "Run hash_map");
run_step_hash_map.dependOn(&run_cmd_hash_map.step);
// Section: "Binary Tree"
// Source File: "chapter_tree/binary_tree.zig"
// Run Command: zig build run_binary_tree
const exe_binary_tree = b.addExecutable("hash_map", "chapter_tree/binary_tree.zig");
exe_binary_tree.addPackagePath("include", "include/include.zig");
exe_binary_tree.setTarget(target);
exe_binary_tree.setBuildMode(mode);
exe_binary_tree.install();
const run_cmd_binary_tree = exe_binary_tree.run();
run_cmd_binary_tree.step.dependOn(b.getInstallStep());
if (b.args) |args| run_cmd_binary_tree.addArgs(args);
const run_step_binary_tree= b.step("run_binary_tree", "Run binary_tree");
run_step_binary_tree.dependOn(&run_cmd_binary_tree.step);
// Section: "Heap"
// Source File: "chapter_heap/heap.zig"
// Run Command: zig build run_heap
const exe_heap = b.addExecutable("heap", "chapter_heap/heap.zig");
exe_heap.addPackagePath("include", "include/include.zig");
exe_heap.setTarget(target);
exe_heap.setBuildMode(mode);
exe_heap.install();
const run_cmd_heap = exe_heap.run();
run_cmd_heap.step.dependOn(b.getInstallStep());
if (b.args) |args| run_cmd_heap.addArgs(args);
const run_step_heap = b.step("run_heap", "Run heap");
run_step_heap.dependOn(&run_cmd_heap.step);
// Section: "Linear Search"
// Source File: "chapter_searching/linear_search.zig"
// Run Command: zig build run_linear_search
const exe_linear_search = b.addExecutable("linear_search", "chapter_searching/linear_search.zig");
exe_linear_search.addPackagePath("include", "include/include.zig");
exe_linear_search.setTarget(target);
exe_linear_search.setBuildMode(mode);
exe_linear_search.install();
const run_cmd_linear_search = exe_linear_search.run();
run_cmd_linear_search.step.dependOn(b.getInstallStep());
if (b.args) |args| run_cmd_linear_search.addArgs(args);
const run_step_linear_search= b.step("run_linear_search", "Run linear_search");
run_step_linear_search.dependOn(&run_cmd_linear_search.step);
// Section: "Bubble Sort"
// Source File: "chapter_sorting/bubble_sort.zig"
// Run Command: zig build run_bubble_sort

View File

@ -0,0 +1,55 @@
// File: hash_map.zig
// Created Time: 2023-01-13
// Author: sjinzh (sjinzh@gmail.com)
const std = @import("std");
const inc = @import("include");
// Driver Code
pub fn main() !void {
//
var map = std.AutoHashMap(i32, []const u8).init(std.heap.page_allocator);
//
defer map.deinit();
//
// (key, value)
try map.put(12836, "小哈");
try map.put(15937, "小啰");
try map.put(16750, "小算");
try map.put(13276, "小法");
try map.put(10583, "小鸭");
std.debug.print("\n添加完成后,哈希表为\nKey -> Value\n", .{});
inc.PrintUtil.printHashMap(i32, []const u8, map);
//
// key value
var name = map.get(15937).?;
std.debug.print("\n输入学号 15937 ,查询到姓名 {s}\n", .{name});
//
// (key, value)
_ = map.remove(10583);
std.debug.print("\n删除 10583 后,哈希表为\nKey -> Value\n", .{});
inc.PrintUtil.printHashMap(i32, []const u8, map);
//
std.debug.print("\n遍历键值对 Key->Value\n", .{});
inc.PrintUtil.printHashMap(i32, []const u8, map);
std.debug.print("\n单独遍历键 Key\n", .{});
var it = map.iterator();
while (it.next()) |kv| {
std.debug.print("{}\n", .{kv.key_ptr.*});
}
std.debug.print("\n单独遍历值 value\n", .{});
it = map.iterator();
while (it.next()) |kv| {
std.debug.print("{s}\n", .{kv.value_ptr.*});
}
const getchar = try std.io.getStdIn().reader().readByte();
_ = getchar;
}

View File

@ -0,0 +1,81 @@
// File: heap.zig
// Created Time: 2023-01-14
// Author: sjinzh (sjinzh@gmail.com)
const std = @import("std");
const inc = @import("include");
fn lessThan(context: void, a: i32, b: i32) std.math.Order {
_ = context;
return std.math.order(a, b);
}
fn greaterThan(context: void, a: i32, b: i32) std.math.Order {
return lessThan(context, a, b).invert();
}
fn testPush(comptime T: type, mem_allocator: std.mem.Allocator, heap: anytype, val: T) !void {
try heap.add(val); //
std.debug.print("\n元素 {} 入堆后\n", .{val});
try inc.PrintUtil.printHeap(T, mem_allocator, heap);
}
fn testPop(comptime T: type, mem_allocator: std.mem.Allocator, heap: anytype) !void {
var val = heap.remove(); //
std.debug.print("\n堆顶元素 {} 出堆后\n", .{val});
try inc.PrintUtil.printHeap(T, mem_allocator, heap);
}
// Driver Code
pub fn main() !void {
//
var mem_arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer mem_arena.deinit();
const mem_allocator = mem_arena.allocator();
//
//
const PQlt = std.PriorityQueue(i32, void, lessThan);
var minHeap = PQlt.init(std.heap.page_allocator, {});
defer minHeap.deinit();
//
const PQgt = std.PriorityQueue(i32, void, greaterThan);
var maxHeap = PQgt.init(std.heap.page_allocator, {});
defer maxHeap.deinit();
std.debug.print("\n以下测试样例为大顶堆", .{});
//
try testPush(i32, mem_allocator, &maxHeap, 1);
try testPush(i32, mem_allocator, &maxHeap, 3);
try testPush(i32, mem_allocator, &maxHeap, 2);
try testPush(i32, mem_allocator, &maxHeap, 5);
try testPush(i32, mem_allocator, &maxHeap, 4);
//
var peek = maxHeap.peek().?;
std.debug.print("\n堆顶元素为 {}\n", .{peek});
//
try testPop(i32, mem_allocator, &maxHeap);
try testPop(i32, mem_allocator, &maxHeap);
try testPop(i32, mem_allocator, &maxHeap);
try testPop(i32, mem_allocator, &maxHeap);
try testPop(i32, mem_allocator, &maxHeap);
//
var size = maxHeap.len;
std.debug.print("\n堆元素数量为 {}\n", .{size});
//
var isEmpty = if (maxHeap.len == 0) true else false;
std.debug.print("\n堆是否为空 {}\n", .{isEmpty});
//
try minHeap.addSlice(&[_]i32{ 1, 3, 2, 5, 4 });
std.debug.print("\n输入列表并建立小顶堆后\n", .{});
try inc.PrintUtil.printHeap(i32, mem_allocator, minHeap);
const getchar = try std.io.getStdIn().reader().readByte();
_ = getchar;
}

View File

@ -0,0 +1,56 @@
// File: linear_search.zig
// Created Time: 2023-01-13
// Author: sjinzh (sjinzh@gmail.com)
const std = @import("std");
const inc = @import("include");
// 线
fn linearSearchList(comptime T: type, nums: std.ArrayList(T), target: T) T {
//
for (nums.items) |num, i| {
//
if (num == target) {
return @intCast(T, i);
}
}
// -1
return -1;
}
// 线
pub fn linearSearchLinkedList(comptime T: type, node: ?*inc.ListNode(T), target: T) ?*inc.ListNode(T) {
var head = node;
//
while (head != null) {
//
if (head.?.val == target) return head;
head = head.?.next;
}
return null;
}
// Driver Code
pub fn main() !void {
var target: i32 = 3;
// 线
var nums = std.ArrayList(i32).init(std.heap.page_allocator);
defer nums.deinit();
try nums.appendSlice(&[_]i32{ 1, 5, 3, 2, 4, 7, 5, 9, 10, 8 });
var index = linearSearchList(i32, nums, target);
std.debug.print("目标元素 3 的索引 = {}\n", .{index});
// 线
var mem_arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer mem_arena.deinit();
const mem_allocator = mem_arena.allocator();
var head = try inc.ListUtil.listToLinkedList(i32, mem_allocator, nums);
var node = linearSearchLinkedList(i32, head, target);
std.debug.print("目标结点值 3 的对应结点对象为 ", .{});
try inc.PrintUtil.printLinkedList(i32, node);
const getchar = try std.io.getStdIn().reader().readByte();
_ = getchar;
}

View File

@ -1,4 +1,4 @@
// File: time_complexity.zig
// File: bubble_sort.zig
// Created Time: 2023-01-08
// Author: sjinzh (sjinzh@gmail.com)

View File

@ -1,4 +1,4 @@
// File: time_complexity.zig
// File: insertion_sort.zig
// Created Time: 2023-01-08
// Author: sjinzh (sjinzh@gmail.com)

View File

@ -1,4 +1,4 @@
// File: stack.zig
// File: array_stack.zig
// Created Time: 2023-01-08
// Author: sjinzh (sjinzh@gmail.com)

View File

@ -0,0 +1,40 @@
// File: binary_tree.zig
// Created Time: 2023-01-14
// Author: sjinzh (sjinzh@gmail.com)
const std = @import("std");
const inc = @import("include");
// Driver Code
pub fn main() !void {
//
//
var n1 = inc.TreeNode(i32){ .val = 1 };
var n2 = inc.TreeNode(i32){ .val = 2 };
var n3 = inc.TreeNode(i32){ .val = 3 };
var n4 = inc.TreeNode(i32){ .val = 4 };
var n5 = inc.TreeNode(i32){ .val = 5 };
//
n1.left = &n2;
n1.right = &n3;
n2.left = &n4;
n2.right = &n5;
std.debug.print("初始化二叉树\n", .{});
try inc.PrintUtil.printTree(&n1, null, false);
//
var p = inc.TreeNode(i32){ .val = 0 };
// n1 -> n2 P
n1.left = &p;
p.left = &n2;
std.debug.print("插入结点 P 后\n", .{});
try inc.PrintUtil.printTree(&n1, null, false);
//
n1.left = &n2;
std.debug.print("删除结点 P 后\n", .{});
try inc.PrintUtil.printTree(&n1, null, false);
const getchar = try std.io.getStdIn().reader().readByte();
_ = getchar;
}

View File

@ -16,6 +16,21 @@ pub fn ListNode(comptime T: type) type {
// Initialize a list node with specific value
pub fn init(self: *Self, x: i32) void {
self.val = x;
self.next = null;
}
};
}
// Generate a linked list with a list
pub fn listToLinkedList(comptime T: type, mem_allocator: std.mem.Allocator, list: std.ArrayList(T)) !?*ListNode(T) {
var dum = try mem_allocator.create(ListNode(T));
dum.init(0);
var head = dum;
for (list.items) |val| {
var tmp = try mem_allocator.create(ListNode(T));
tmp.init(val);
head.next = tmp;
head = head.next.?;
}
return dum.next;
}

View File

@ -3,8 +3,10 @@
// Author: sjinzh (sjinzh@gmail.com)
const std = @import("std");
const ListNode = @import("ListNode.zig").ListNode;
const TreeNode = @import("TreeNode.zig").TreeNode;
pub const ListUtil = @import("ListNode.zig");
pub const ListNode = ListUtil.ListNode;
pub const TreeUtil = @import("TreeNode.zig");
pub const TreeNode = TreeUtil.TreeNode;
// Print an array
pub fn printArray(comptime T: type, nums: []T) void {
@ -46,6 +48,27 @@ pub fn printLinkedList(comptime T: type, node: ?*ListNode(T)) !void {
}
}
// Print a HashMap
pub fn printHashMap(comptime TKey: type, comptime TValue: type, map: std.AutoHashMap(TKey, TValue)) void {
var it = map.iterator();
while (it.next()) |kv| {
var key = kv.key_ptr.*;
var value = kv.value_ptr.*;
std.debug.print("{} -> {s}\n", .{key, value});
}
}
// print a heap (PriorityQueue)
pub fn printHeap(comptime T: type, mem_allocator: std.mem.Allocator, queue: anytype) !void {
var arr = queue.items;
var len = queue.len;
std.debug.print("堆的数组表示:", .{});
printArray(T, arr[0..len]);
std.debug.print("\n堆的树状表示:\n", .{});
var root = try TreeUtil.arrToTree(T, mem_allocator, arr[0..len]);
try printTree(root, null, false);
}
// This tree printer is borrowed from TECHIE DELIGHT
// https://www.techiedelight.com/c-program-print-binary-tree/
const Trunk = struct {

View File

@ -17,6 +17,46 @@ pub fn TreeNode(comptime T: type) type {
// Initialize a tree node with specific value
pub fn init(self: *Self, x: i32) void {
self.val = x;
self.left = null;
self.right = null;
}
};
}
// Generate a binary tree with an array
pub fn arrToTree(comptime T: type, mem_allocator: std.mem.Allocator, arr: []T) !?*TreeNode(T) {
if (arr.len == 0) return null;
var root = try mem_allocator.create(TreeNode(T));
root.init(arr[0]);
const L = std.TailQueue(*TreeNode(T));
var que = L{};
var root_node = try mem_allocator.create(L.Node);
root_node.data = root;
que.append(root_node);
var index: usize = 0;
while (que.len > 0) {
var que_node = que.popFirst().?;
var node = que_node.data;
index += 1;
if (index >= arr.len) break;
if (index < arr.len) {
var tmp = try mem_allocator.create(TreeNode(T));
tmp.init(arr[index]);
node.left = tmp;
var tmp_node = try mem_allocator.create(L.Node);
tmp_node.data = node.left.?;
que.append(tmp_node);
}
index += 1;
if (index >= arr.len) break;
if (index < arr.len) {
var tmp = try mem_allocator.create(TreeNode(T));
tmp.init(arr[index]);
node.right = tmp;
var tmp_node = try mem_allocator.create(L.Node);
tmp_node.data = node.right.?;
que.append(tmp_node);
}
}
return root;
}

View File

@ -3,5 +3,7 @@
// Author: sjinzh (sjinzh@gmail.com)
pub const PrintUtil = @import("PrintUtil.zig");
pub const ListNode = @import("ListNode.zig").ListNode;
pub const TreeNode = @import("TreeNode.zig").TreeNode;
pub const ListUtil = @import("ListNode.zig");
pub const ListNode = ListUtil.ListNode;
pub const TreeUtil = @import("TreeNode.zig");
pub const TreeNode = TreeUtil.TreeNode;

View File

@ -245,6 +245,8 @@ elementAddr = firtstElementAddr + elementLength * elementIndex
for (int i = 0; i < size; i++) {
res[i] = nums[i];
}
// 释放内存
delete[] nums;
// 返回扩展后的新数组
return res;
}

View File

@ -748,6 +748,11 @@ comments: true
nums = new int[numsCapacity];
}
/* 析构函数 */
~MyList() {
delete[] nums;
}
/* 获取列表长度(即当前元素数量)*/
int size() {
return numsSize;
@ -818,14 +823,14 @@ comments: true
void extendCapacity() {
// 新建一个长度为 size * extendRatio 的数组,并将原数组拷贝到新数组
int newCapacity = capacity() * extendRatio;
int* extend = new int[newCapacity];
int* tmp = nums;
nums = new int[newCapacity];
// 将原数组中的所有元素复制到新数组
for (int i = 0; i < size(); i++) {
extend[i] = nums[i];
nums[i] = tmp[i];
}
int* temp = nums;
nums = extend;
delete[] temp;
// 释放内存
delete[] tmp;
numsCapacity = newCapacity;
}
};

View File

@ -507,7 +507,7 @@ $$
const int a = 0;
int b = 0;
vector<int> nums(10000);
ListNode* node = new ListNode(0);
ListNode node(0);
// 循环中的变量占用 O(1) 空间
for (int i = 0; i < n; i++) {
int c = 0;
@ -654,9 +654,9 @@ $$
// 长度为 n 的数组占用 O(n) 空间
vector<int> nums(n);
// 长度为 n 的列表占用 O(n) 空间
vector<ListNode*> nodes;
vector<ListNode> nodes;
for (int i = 0; i < n; i++) {
nodes.push_back(new ListNode(i));
nodes.push_back(ListNode(i));
}
// 长度为 n 的哈希表占用 O(n) 空间
unordered_map<int, string> map;

View File

@ -606,6 +606,7 @@ comments: true
// 判空处理
if h.isEmpty() {
fmt.Println("error")
return nil
}
// 交换根结点与最右叶结点(即交换首元素与尾元素)
h.swap(0, h.size()-1)

View File

@ -16,20 +16,28 @@ comments: true
=== "Step 1"
![pivot_division_step1](quick_sort.assets/pivot_division_step1.png)
=== "Step 2"
![pivot_division_step2](quick_sort.assets/pivot_division_step2.png)
=== "Step 3"
![pivot_division_step3](quick_sort.assets/pivot_division_step3.png)
=== "Step 4"
![pivot_division_step4](quick_sort.assets/pivot_division_step4.png)
=== "Step 5"
![pivot_division_step5](quick_sort.assets/pivot_division_step5.png)
=== "Step 6"
![pivot_division_step6](quick_sort.assets/pivot_division_step6.png)
=== "Step 7"
![pivot_division_step7](quick_sort.assets/pivot_division_step7.png)
=== "Step 8"
![pivot_division_step8](quick_sort.assets/pivot_division_step8.png)
=== "Step 9"
![pivot_division_step9](quick_sort.assets/pivot_division_step9.png)
@ -134,27 +142,27 @@ comments: true
``` js title="quick_sort.js"
/* 元素交换 */
function swap(nums, i, j) {
let tmp = nums[i]
nums[i] = nums[j]
nums[j] = tmp
let tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
/* 哨兵划分 */
function partition(nums, left, right){
function partition(nums, left, right) {
// 以 nums[left] 作为基准数
let i = left, j = right
while(i < j){
while(i < j && nums[j] >= nums[left]){
j -= 1 // 从右向左找首个小于基准数的元素
let i = left, j = right;
while (i < j) {
while (i < j && nums[j] >= nums[left]) {
j -= 1; // 从右向左找首个小于基准数的元素
}
while(i < j && nums[i] <= nums[left]){
i += 1 // 从左向右找首个大于基准数的元素
while (i < j && nums[i] <= nums[left]) {
i += 1; // 从左向右找首个大于基准数的元素
}
// 元素交换
swap(nums, i, j) // 交换这两个元素
swap(nums, i, j); // 交换这两个元素
}
swap(nums, i, left) // 将基准数交换至两子数组的分界线
return i // 返回基准数的索引
swap(nums, i, left); // 将基准数交换至两子数组的分界线
return i; // 返回基准数的索引
}
```
@ -220,7 +228,6 @@ comments: true
swap(nums, i, left); // 将基准数交换至两子数组的分界线
return i; // 返回基准数的索引
}
```
=== "Swift"
@ -313,14 +320,14 @@ comments: true
```js title="quick_sort.js"
/* 快速排序 */
function quickSort(nums, left, right){
function quickSort(nums, left, right) {
// 子数组长度为 1 时终止递归
if(left >= right) return
if (left >= right) return;
// 哨兵划分
const pivot = partition(nums, left, right)
const pivot = partition(nums, left, right);
// 递归左子数组、右子数组
quick_sort(nums, left, pivot - 1)
quick_sort(nums, pivot + 1, right)
quickSort(nums, left, pivot - 1);
quickSort(nums, pivot + 1, right);
}
```
@ -408,7 +415,7 @@ comments: true
int medianThree(int[] nums, int left, int mid, int right) {
// 使用了异或操作来简化代码
// 异或规则为 0 ^ 0 = 1 ^ 1 = 0, 0 ^ 1 = 1 ^ 0 = 1
if ((nums[left] > nums[mid]) ^ (nums[left] > nums[right]))
if ((nums[left] < nums[mid]) ^ (nums[left] < nums[right]))
return left;
else if ((nums[mid] < nums[left]) ^ (nums[mid] < nums[right]))
return mid;
@ -434,7 +441,7 @@ comments: true
int medianThree(vector<int>& nums, int left, int mid, int right) {
// 使用了异或操作来简化代码
// 异或规则为 0 ^ 0 = 1 ^ 1 = 0, 0 ^ 1 = 1 ^ 0 = 1
if ((nums[left] > nums[mid]) ^ (nums[left] > nums[right]))
if ((nums[left] < nums[mid]) ^ (nums[left] < nums[right]))
return left;
else if ((nums[mid] < nums[left]) ^ (nums[mid] < nums[right]))
return mid;
@ -460,7 +467,7 @@ comments: true
def median_three(self, nums, left, mid, right):
# 使用了异或操作来简化代码
# 异或规则为 0 ^ 0 = 1 ^ 1 = 0, 0 ^ 1 = 1 ^ 0 = 1
if (nums[left] > nums[mid]) ^ (nums[left] > nums[right]):
if (nums[left] < nums[mid]) ^ (nums[left] < nums[right]):
return left
elif (nums[mid] < nums[left]) ^ (nums[mid] > nums[right]):
return mid
@ -481,9 +488,9 @@ comments: true
```go title="quick_sort.go"
/* 选取三个元素的中位数 */
func medianThree(nums []int, left, mid, right int) int {
if (nums[left] > nums[mid]) != (nums[left] > nums[right]) {
if (nums[left] < nums[mid]) != (nums[left] < nums[right]) {
return left
} else if (nums[mid] < nums[left]) != (nums[mid] > nums[right]) {
} else if (nums[mid] > nums[left]) != (nums[mid] > nums[right]) {
return mid
}
return right
@ -507,7 +514,7 @@ comments: true
function medianThree(nums, left, mid, right) {
// 使用了异或操作来简化代码
// 异或规则为 0 ^ 0 = 1 ^ 1 = 0, 0 ^ 1 = 1 ^ 0 = 1
if ((nums[left] > nums[mid]) ^ (nums[left] > nums[right]))
if ((nums[left] < nums[mid]) ^ (nums[left] < nums[right]))
return left;
else if ((nums[mid] < nums[left]) ^ (nums[mid] < nums[right]))
return mid;
@ -533,7 +540,7 @@ comments: true
function medianThree(nums: number[], left: number, mid: number, right: number): number {
// 使用了异或操作来简化代码
// 异或规则为 0 ^ 0 = 1 ^ 1 = 0, 0 ^ 1 = 1 ^ 0 = 1
if (Number(nums[left] > nums[mid]) ^ Number(nums[left] > nums[right])) {
if (Number(nums[left] < nums[mid]) ^ Number(nums[left] < nums[right])) {
return left;
} else if (Number(nums[mid] < nums[left]) ^ Number(nums[mid] < nums[right])) {
return mid;
@ -566,7 +573,7 @@ comments: true
{
// 使用了异或操作来简化代码
// 异或规则为 0 ^ 0 = 1 ^ 1 = 0, 0 ^ 1 = 1 ^ 0 = 1
if ((nums[left] > nums[mid]) ^ (nums[left] > nums[right]))
if ((nums[left] < nums[mid]) ^ (nums[left] < nums[right]))
return left;
else if ((nums[mid] < nums[left]) ^ (nums[mid] < nums[right]))
return mid;

View File

@ -196,5 +196,29 @@ comments: true
=== "Swift"
```swift title="deque.swift"
/* 初始化双向队列 */
// Swift 没有内置的双向队列类,可以把 Array 当作双向队列来使用
var deque: [Int] = []
/* 元素入队 */
deque.append(2) // 添加至队尾
deque.append(5)
deque.append(4)
deque.insert(3, at: 0) // 添加至队首
deque.insert(1, at: 0)
/* 访问元素 */
let peekFirst = deque.first! // 队首元素
let peekLast = deque.last! // 队尾元素
/* 元素出队 */
// 使用 Array 模拟时 pollFirst 的复杂度为 O(n)
let pollFirst = deque.removeFirst() // 队首元素出队
let pollLast = deque.removeLast() // 队尾元素出队
/* 获取双向队列的长度 */
let size = deque.count
/* 判断双向队列是否为空 */
let isEmpty = deque.isEmpty
```

View File

@ -246,6 +246,7 @@ comments: true
let peek = queue.first!
/* 元素出队 */
// 使用 Array 模拟时 poll 的复杂度为 O(n)
let pool = queue.removeFirst()
/* 获取队列的长度 */
@ -330,6 +331,10 @@ comments: true
rear = nullptr;
queSize = 0;
}
~LinkedListQueue() {
delete front;
delete rear;
}
/* 获取队列的长度 */
int size() {
return queSize;
@ -784,6 +789,9 @@ comments: true
cap = capacity;
nums = new int[capacity];
}
~ArrayQueue() {
delete[] nums;
}
/* 获取队列的容量 */
int capacity() {
return cap;

View File

@ -324,6 +324,9 @@ comments: true
stackTop = nullptr;
stkSize = 0;
}
~LinkedListStack() {
freeMemoryLinkedList(stackTop);
}
/* 获取栈的长度 */
int size() {
return stkSize;

View File

@ -22,19 +22,15 @@ comments: true
- 若 `cur.val = num` ,说明找到目标结点,跳出循环并返回该结点即可;
=== "Step 1"
![bst_search_1](binary_search_tree.assets/bst_search_1.png)
=== "Step 2"
![bst_search_2](binary_search_tree.assets/bst_search_2.png)
=== "Step 3"
![bst_search_3](binary_search_tree.assets/bst_search_3.png)
=== "Step 4"
![bst_search_4](binary_search_tree.assets/bst_search_4.png)
二叉搜索树的查找操作和二分查找算法如出一辙,也是在每轮排除一半情况。循环次数最多为二叉树的高度,当二叉树平衡时,使用 $O(\log n)$ 时间。
@ -483,9 +479,9 @@ comments: true
// 找到待删除结点,跳出循环
if (cur.val == num) break;
pre = cur;
// 待删除结点在 root 的右子树中
// 待删除结点在 cur 的右子树中
if (cur.val < num) cur = cur.right;
// 待删除结点在 root 的左子树中
// 待删除结点在 cur 的左子树中
else cur = cur.left;
}
// 若无待删除结点,则直接返回
@ -527,9 +523,9 @@ comments: true
// 找到待删除结点,跳出循环
if (cur->val == num) break;
pre = cur;
// 待删除结点在 root 的右子树中
// 待删除结点在 cur 的右子树中
if (cur->val < num) cur = cur->right;
// 待删除结点在 root 的左子树中
// 待删除结点在 cur 的左子树中
else cur = cur->left;
}
// 若无待删除结点,则直接返回
@ -575,9 +571,9 @@ comments: true
if cur.val == num:
break
pre = cur
if cur.val < num: # 待删除结点在 root 的右子树中
if cur.val < num: # 待删除结点在 cur 的右子树中
cur = cur.right
else: # 待删除结点在 root 的左子树中
else: # 待删除结点在 cur 的左子树中
cur = cur.left
# 若无待删除结点,则直接返回
@ -677,9 +673,9 @@ comments: true
// 找到待删除结点,跳出循环
if (cur.val === num) break;
pre = cur;
// 待删除结点在 root 的右子树中
// 待删除结点在 cur 的右子树中
if (cur.val < num) cur = cur.right;
// 待删除结点在 root 的左子树中
// 待删除结点在 cur 的左子树中
else cur = cur.left;
}
// 若无待删除结点,则直接返回
@ -725,9 +721,9 @@ comments: true
}
pre = cur;
if (cur.val < num) {
cur = cur.right as TreeNode; // 待删除结点在 root 的右子树中
cur = cur.right as TreeNode; // 待删除结点在 cur 的右子树中
} else {
cur = cur.left as TreeNode; // 待删除结点在 root 的左子树中
cur = cur.left as TreeNode; // 待删除结点在 cur 的左子树中
}
}
// 若无待删除结点,则直接返回
@ -780,9 +776,9 @@ comments: true
// 找到待删除结点,跳出循环
if (cur.val == num) break;
pre = cur;
// 待删除结点在 root 的右子树中
// 待删除结点在 cur 的右子树中
if (cur.val < num) cur = cur.right;
// 待删除结点在 root 的左子树中
// 待删除结点在 cur 的左子树中
else cur = cur.left;
}
// 若无待删除结点,则直接返回

Binary file not shown.

Before

Width:  |  Height:  |  Size: 127 KiB

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 172 KiB

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 217 KiB

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 177 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 318 KiB

After

Width:  |  Height:  |  Size: 177 KiB