Merge branch 'krahets:master' into master
15
.gitattributes
vendored
Normal 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
|
@ -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;
|
||||
}
|
||||
|
@ -83,5 +83,8 @@ int main() {
|
||||
int index = find(n0, 2);
|
||||
cout << "链表中值为 2 的结点的索引 = " << index << endl;
|
||||
|
||||
// 释放内存
|
||||
freeMemoryLinkedList(n0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -56,5 +56,9 @@ int main() {
|
||||
cout << "方法二 res = ";
|
||||
PrintUtil::printVector(res);
|
||||
|
||||
// 释放内存
|
||||
delete slt1;
|
||||
delete slt2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -78,5 +78,8 @@ int main() {
|
||||
bool empty = stack->empty();
|
||||
cout << "栈是否为空 = " << empty << endl;
|
||||
|
||||
// 释放内存
|
||||
delete stack;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -37,5 +37,8 @@ int main() {
|
||||
cout << endl << "删除结点 P 后\n" << endl;
|
||||
PrintUtil::printTree(n1);
|
||||
|
||||
// 释放内存
|
||||
freeMemoryTree(n1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
// 若无待删除结点,则直接返回
|
||||
|
@ -98,6 +98,7 @@ func (h *maxHeap) poll() any {
|
||||
// 判空处理
|
||||
if h.isEmpty() {
|
||||
fmt.Println("error")
|
||||
return nil
|
||||
}
|
||||
// 交换根结点与最右叶结点(即交换首元素与尾元素)
|
||||
h.swap(0, h.size()-1)
|
||||
|
@ -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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* File: my_heap.java
|
||||
* File: heap.java
|
||||
* Created Time: 2023-01-07
|
||||
* Author: Krahets (krahets@163.com)
|
||||
*/
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
// 若无待删除结点,则直接返回
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
// 若无待删除结点,则直接返回
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
# 若无待删除结点,则直接返回
|
||||
|
@ -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"]),
|
||||
]
|
||||
)
|
||||
|
44
codes/swift/chapter_stack_and_queue/deque.swift
Normal 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)")
|
||||
}
|
||||
}
|
@ -25,6 +25,7 @@ enum Queue {
|
||||
print("队首元素 peek = \(peek)")
|
||||
|
||||
/* 元素出队 */
|
||||
// 使用 Array 模拟时 poll 的复杂度为 O(n)
|
||||
let pool = queue.removeFirst()
|
||||
print("出队元素 poll = \(pool),出队后 queue = \(queue)")
|
||||
|
||||
|
@ -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++];
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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 的左子树中
|
||||
}
|
||||
}
|
||||
// 若无待删除结点,则直接返回
|
||||
|
@ -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
|
||||
|
55
codes/zig/chapter_hashing/hash_map.zig
Normal 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;
|
||||
}
|
||||
|
81
codes/zig/chapter_heap/heap.zig
Normal 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;
|
||||
}
|
56
codes/zig/chapter_searching/linear_search.zig
Normal 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;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// File: time_complexity.zig
|
||||
// File: bubble_sort.zig
|
||||
// Created Time: 2023-01-08
|
||||
// Author: sjinzh (sjinzh@gmail.com)
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// File: time_complexity.zig
|
||||
// File: insertion_sort.zig
|
||||
// Created Time: 2023-01-08
|
||||
// Author: sjinzh (sjinzh@gmail.com)
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// File: stack.zig
|
||||
// File: array_stack.zig
|
||||
// Created Time: 2023-01-08
|
||||
// Author: sjinzh (sjinzh@gmail.com)
|
||||
|
||||
|
40
codes/zig/chapter_tree/binary_tree.zig
Normal 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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
@ -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;
|
@ -245,6 +245,8 @@ elementAddr = firtstElementAddr + elementLength * elementIndex
|
||||
for (int i = 0; i < size; i++) {
|
||||
res[i] = nums[i];
|
||||
}
|
||||
// 释放内存
|
||||
delete[] nums;
|
||||
// 返回扩展后的新数组
|
||||
return res;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -606,6 +606,7 @@ comments: true
|
||||
// 判空处理
|
||||
if h.isEmpty() {
|
||||
fmt.Println("error")
|
||||
return nil
|
||||
}
|
||||
// 交换根结点与最右叶结点(即交换首元素与尾元素)
|
||||
h.swap(0, h.size()-1)
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
```
|
||||
|
@ -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;
|
||||
|
@ -324,6 +324,9 @@ comments: true
|
||||
stackTop = nullptr;
|
||||
stkSize = 0;
|
||||
}
|
||||
~LinkedListStack() {
|
||||
freeMemoryLinkedList(stackTop);
|
||||
}
|
||||
/* 获取栈的长度 */
|
||||
int size() {
|
||||
return stkSize;
|
||||
|
@ -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;
|
||||
}
|
||||
// 若无待删除结点,则直接返回
|
||||
|
Before Width: | Height: | Size: 127 KiB After Width: | Height: | Size: 96 KiB |
Before Width: | Height: | Size: 172 KiB After Width: | Height: | Size: 110 KiB |
Before Width: | Height: | Size: 217 KiB After Width: | Height: | Size: 92 KiB |
Before Width: | Height: | Size: 177 KiB |
Before Width: | Height: | Size: 80 KiB |
Before Width: | Height: | Size: 318 KiB After Width: | Height: | Size: 177 KiB |