mirror of
https://github.com/krahets/hello-algo.git
synced 2025-01-23 22:40:25 +08:00
Fix C++, JS, and TS blocks for the code building
This commit is contained in:
parent
6cce1ab059
commit
12c085a088
@ -347,255 +347,17 @@ comments: true
|
|||||||
=== "JavaScript"
|
=== "JavaScript"
|
||||||
|
|
||||||
```javascript title="linkedlist_deque.js"
|
```javascript title="linkedlist_deque.js"
|
||||||
/* 双向链表结点 */
|
[class]{ListNode}-[func]{}
|
||||||
class ListNode {
|
|
||||||
prev; // 前驱结点引用 (指针)
|
|
||||||
next; // 后继结点引用 (指针)
|
|
||||||
val; // 结点值
|
|
||||||
|
|
||||||
constructor(val) {
|
|
||||||
this.val = val;
|
|
||||||
this.next = null;
|
|
||||||
this.prev = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 基于双向链表实现的双向队列 */
|
[class]{LinkedListDeque}-[func]{}
|
||||||
class LinkedListDeque {
|
|
||||||
front; // 头结点 front
|
|
||||||
rear; // 尾结点 rear
|
|
||||||
len; // 双向队列的长度
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
this.front = null;
|
|
||||||
this.rear = null;
|
|
||||||
this.len = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 队尾入队操作 */
|
|
||||||
pushLast(val) {
|
|
||||||
const node = new ListNode(val);
|
|
||||||
// 若链表为空,则令 front, rear 都指向 node
|
|
||||||
if (this.len === 0) {
|
|
||||||
this.front = node;
|
|
||||||
this.rear = node;
|
|
||||||
} else {
|
|
||||||
// 将 node 添加至链表尾部
|
|
||||||
this.rear.next = node;
|
|
||||||
node.prev = this.rear;
|
|
||||||
this.rear = node; // 更新尾结点
|
|
||||||
}
|
|
||||||
this.len++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 队首入队操作 */
|
|
||||||
pushFirst(val) {
|
|
||||||
const node = new ListNode(val);
|
|
||||||
// 若链表为空,则令 front, rear 都指向 node
|
|
||||||
if (this.len === 0) {
|
|
||||||
this.front = node;
|
|
||||||
this.rear = node;
|
|
||||||
} else {
|
|
||||||
// 将 node 添加至链表头部
|
|
||||||
this.front.prev = node;
|
|
||||||
node.next = this.front;
|
|
||||||
this.front = node; // 更新头结点
|
|
||||||
}
|
|
||||||
this.len++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 队尾出队操作 */
|
|
||||||
pollLast() {
|
|
||||||
if (this.len === 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
const value = this.rear.val; // 存储尾结点值
|
|
||||||
// 删除尾结点
|
|
||||||
let temp = this.rear.prev;
|
|
||||||
if (temp !== null) {
|
|
||||||
temp.next = null;
|
|
||||||
this.rear.prev = null;
|
|
||||||
}
|
|
||||||
this.rear = temp; // 更新尾结点
|
|
||||||
this.len--;
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 队首出队操作 */
|
|
||||||
pollFirst() {
|
|
||||||
if (this.len === 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
const value = this.front.val; // 存储尾结点值
|
|
||||||
// 删除头结点
|
|
||||||
let temp = this.front.next;
|
|
||||||
if (temp !== null) {
|
|
||||||
temp.prev = null;
|
|
||||||
this.front.next = null;
|
|
||||||
}
|
|
||||||
this.front = temp; // 更新头结点
|
|
||||||
this.len--;
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 访问队尾元素 */
|
|
||||||
peekLast() {
|
|
||||||
return this.len === 0 ? null : this.rear.val;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 访问队首元素 */
|
|
||||||
peekFirst() {
|
|
||||||
return this.len === 0 ? null : this.front.val;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 获取双向队列的长度 */
|
|
||||||
size() {
|
|
||||||
return this.len;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 判断双向队列是否为空 */
|
|
||||||
isEmpty() {
|
|
||||||
return this.len === 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 打印双向队列 */
|
|
||||||
print() {
|
|
||||||
const arr = [];
|
|
||||||
let temp = this.front;
|
|
||||||
while (temp !== null) {
|
|
||||||
arr.push(temp.val);
|
|
||||||
temp = temp.next;
|
|
||||||
}
|
|
||||||
console.log("[" + arr.join(", ") + "]");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "TypeScript"
|
=== "TypeScript"
|
||||||
|
|
||||||
```typescript title="linkedlist_deque.ts"
|
```typescript title="linkedlist_deque.ts"
|
||||||
/* 双向链表结点 */
|
[class]{ListNode}-[func]{}
|
||||||
class ListNode {
|
|
||||||
prev: ListNode; // 前驱结点引用 (指针)
|
|
||||||
next: ListNode; // 后继结点引用 (指针)
|
|
||||||
val: number; // 结点值
|
|
||||||
|
|
||||||
constructor(val: number) {
|
[class]{LinkedListDeque}-[func]{}
|
||||||
this.val = val;
|
|
||||||
this.next = null;
|
|
||||||
this.prev = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 基于双向链表实现的双向队列 */
|
|
||||||
class LinkedListDeque {
|
|
||||||
front: ListNode; // 头结点 front
|
|
||||||
rear: ListNode; // 尾结点 rear
|
|
||||||
len: number; // 双向队列的长度
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
this.front = null;
|
|
||||||
this.rear = null;
|
|
||||||
this.len = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 队尾入队操作 */
|
|
||||||
pushLast(val: number): void {
|
|
||||||
const node: ListNode = new ListNode(val);
|
|
||||||
// 若链表为空,则令 front, rear 都指向 node
|
|
||||||
if (this.len === 0) {
|
|
||||||
this.front = node;
|
|
||||||
this.rear = node;
|
|
||||||
} else {
|
|
||||||
// 将 node 添加至链表尾部
|
|
||||||
this.rear.next = node;
|
|
||||||
node.prev = this.rear;
|
|
||||||
this.rear = node; // 更新尾结点
|
|
||||||
}
|
|
||||||
this.len++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 队首入队操作 */
|
|
||||||
pushFirst(val: number): void {
|
|
||||||
const node: ListNode = new ListNode(val);
|
|
||||||
// 若链表为空,则令 front, rear 都指向 node
|
|
||||||
if (this.len === 0) {
|
|
||||||
this.front = node;
|
|
||||||
this.rear = node;
|
|
||||||
} else {
|
|
||||||
// 将 node 添加至链表头部
|
|
||||||
this.front.prev = node;
|
|
||||||
node.next = this.front;
|
|
||||||
this.front = node; // 更新头结点
|
|
||||||
}
|
|
||||||
this.len++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 队尾出队操作 */
|
|
||||||
pollLast(): number {
|
|
||||||
if (this.len === 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
const value: number = this.rear.val; // 存储尾结点值
|
|
||||||
// 删除尾结点
|
|
||||||
let temp: ListNode = this.rear.prev;
|
|
||||||
if (temp !== null) {
|
|
||||||
temp.next = null;
|
|
||||||
this.rear.prev = null;
|
|
||||||
}
|
|
||||||
this.rear = temp; // 更新尾结点
|
|
||||||
this.len--;
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 队首出队操作 */
|
|
||||||
pollFirst(): number {
|
|
||||||
if (this.len === 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
const value: number = this.front.val; // 存储尾结点值
|
|
||||||
// 删除头结点
|
|
||||||
let temp: ListNode = this.front.next;
|
|
||||||
if (temp !== null) {
|
|
||||||
temp.prev = null;
|
|
||||||
this.front.next = null;
|
|
||||||
}
|
|
||||||
this.front = temp; // 更新头结点
|
|
||||||
this.len--;
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 访问队尾元素 */
|
|
||||||
peekLast(): number {
|
|
||||||
return this.len === 0 ? null : this.rear.val;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 访问队首元素 */
|
|
||||||
peekFirst(): number {
|
|
||||||
return this.len === 0 ? null : this.front.val;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 获取双向队列的长度 */
|
|
||||||
size(): number {
|
|
||||||
return this.len;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 判断双向队列是否为空 */
|
|
||||||
isEmpty(): boolean {
|
|
||||||
return this.len === 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 打印双向队列 */
|
|
||||||
print(): void {
|
|
||||||
const arr: number[] = [];
|
|
||||||
let temp: ListNode = this.front;
|
|
||||||
while (temp !== null) {
|
|
||||||
arr.push(temp.val);
|
|
||||||
temp = temp.next;
|
|
||||||
}
|
|
||||||
console.log("[" + arr.join(", ") + "]");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "C"
|
=== "C"
|
||||||
|
@ -166,17 +166,9 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit
|
|||||||
=== "C++"
|
=== "C++"
|
||||||
|
|
||||||
```cpp title="avl_tree.cpp"
|
```cpp title="avl_tree.cpp"
|
||||||
/* 获取结点高度 */
|
[class]{AVLTree}-[func]{height}
|
||||||
int height(TreeNode* node) {
|
|
||||||
// 空结点高度为 -1 ,叶结点高度为 0
|
|
||||||
return node == nullptr ? -1 : node->height;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 更新结点高度 */
|
[class]{AVLTree}-[func]{updateHeight}
|
||||||
void updateHeight(TreeNode* node) {
|
|
||||||
// 结点高度等于最高子树高度 + 1
|
|
||||||
node->height = max(height(node->left), height(node->right)) + 1;
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "Python"
|
=== "Python"
|
||||||
@ -215,33 +207,17 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit
|
|||||||
=== "JavaScript"
|
=== "JavaScript"
|
||||||
|
|
||||||
```javascript title="avl_tree.js"
|
```javascript title="avl_tree.js"
|
||||||
/* 获取结点高度 */
|
[class]{AVLTree}-[func]{height}
|
||||||
height(node) {
|
|
||||||
// 空结点高度为 -1 ,叶结点高度为 0
|
|
||||||
return node === null ? -1 : node.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 更新结点高度 */
|
[class]{AVLTree}-[func]{updateHeight}
|
||||||
updateHeight(node) {
|
|
||||||
// 结点高度等于最高子树高度 + 1
|
|
||||||
node.height = Math.max(this.height(node.left), this.height(node.right)) + 1;
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "TypeScript"
|
=== "TypeScript"
|
||||||
|
|
||||||
```typescript title="avl_tree.ts"
|
```typescript title="avl_tree.ts"
|
||||||
/* 获取结点高度 */
|
[class]{AVLTree}-[func]{height}
|
||||||
height(node: TreeNode): number {
|
|
||||||
// 空结点高度为 -1 ,叶结点高度为 0
|
|
||||||
return node === null ? -1 : node.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 更新结点高度 */
|
[class]{AVLTree}-[func]{updateHeight}
|
||||||
updateHeight(node: TreeNode): void {
|
|
||||||
// 结点高度等于最高子树高度 + 1
|
|
||||||
node.height = Math.max(this.height(node.left), this.height(node.right)) + 1;
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "C"
|
=== "C"
|
||||||
@ -261,17 +237,9 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit
|
|||||||
=== "Swift"
|
=== "Swift"
|
||||||
|
|
||||||
```swift title="avl_tree.swift"
|
```swift title="avl_tree.swift"
|
||||||
/* 获取结点高度 */
|
[class]{AVLTree}-[func]{height}
|
||||||
func height(node: TreeNode?) -> Int {
|
|
||||||
// 空结点高度为 -1 ,叶结点高度为 0
|
|
||||||
node == nil ? -1 : node!.height
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 更新结点高度 */
|
[class]{AVLTree}-[func]{updateHeight}
|
||||||
func updateHeight(node: TreeNode?) {
|
|
||||||
// 结点高度等于最高子树高度 + 1
|
|
||||||
node?.height = max(height(node: node?.left), height(node: node?.right)) + 1
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "Zig"
|
=== "Zig"
|
||||||
@ -683,28 +651,9 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影
|
|||||||
=== "C++"
|
=== "C++"
|
||||||
|
|
||||||
```cpp title="avl_tree.cpp"
|
```cpp title="avl_tree.cpp"
|
||||||
/* 插入结点 */
|
[class]{AVLTree}-[func]{insert}
|
||||||
TreeNode* insert(int val) {
|
|
||||||
root = insertHelper(root, val);
|
|
||||||
return root;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 递归插入结点(辅助函数) */
|
[class]{AVLTree}-[func]{insertHelper}
|
||||||
TreeNode* insertHelper(TreeNode* node, int val) {
|
|
||||||
if (node == nullptr) return new TreeNode(val);
|
|
||||||
/* 1. 查找插入位置,并插入结点 */
|
|
||||||
if (val < node->val)
|
|
||||||
node->left = insertHelper(node->left, val);
|
|
||||||
else if (val > node->val)
|
|
||||||
node->right = insertHelper(node->right, val);
|
|
||||||
else
|
|
||||||
return node; // 重复结点不插入,直接返回
|
|
||||||
updateHeight(node); // 更新结点高度
|
|
||||||
/* 2. 执行旋转操作,使该子树重新恢复平衡 */
|
|
||||||
node = rotate(node);
|
|
||||||
// 返回子树的根结点
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "Python"
|
=== "Python"
|
||||||
@ -749,53 +698,17 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影
|
|||||||
=== "JavaScript"
|
=== "JavaScript"
|
||||||
|
|
||||||
```javascript title="avl_tree.js"
|
```javascript title="avl_tree.js"
|
||||||
/* 插入结点 */
|
[class]{AVLTree}-[func]{insert}
|
||||||
insert(val) {
|
|
||||||
this.root = this.insertHelper(this.root, val);
|
|
||||||
return this.root;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 递归插入结点(辅助函数) */
|
[class]{AVLTree}-[func]{insertHelper}
|
||||||
insertHelper(node, val) {
|
|
||||||
if (node === null) return new TreeNode(val);
|
|
||||||
/* 1. 查找插入位置,并插入结点 */
|
|
||||||
if (val < node.val) node.left = this.insertHelper(node.left, val);
|
|
||||||
else if (val > node.val) node.right = this.insertHelper(node.right, val);
|
|
||||||
else return node; // 重复结点不插入,直接返回
|
|
||||||
this.updateHeight(node); // 更新结点高度
|
|
||||||
/* 2. 执行旋转操作,使该子树重新恢复平衡 */
|
|
||||||
node = this.rotate(node);
|
|
||||||
// 返回子树的根结点
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "TypeScript"
|
=== "TypeScript"
|
||||||
|
|
||||||
```typescript title="avl_tree.ts"
|
```typescript title="avl_tree.ts"
|
||||||
/* 插入结点 */
|
[class]{AVLTree}-[func]{insert}
|
||||||
insert(val: number): TreeNode {
|
|
||||||
this.root = this.insertHelper(this.root, val);
|
|
||||||
return this.root;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 递归插入结点(辅助函数) */
|
[class]{AVLTree}-[func]{insertHelper}
|
||||||
insertHelper(node: TreeNode, val: number): TreeNode {
|
|
||||||
if (node === null) return new TreeNode(val);
|
|
||||||
/* 1. 查找插入位置,并插入结点 */
|
|
||||||
if (val < node.val) {
|
|
||||||
node.left = this.insertHelper(node.left, val);
|
|
||||||
} else if (val > node.val) {
|
|
||||||
node.right = this.insertHelper(node.right, val);
|
|
||||||
} else {
|
|
||||||
return node; // 重复结点不插入,直接返回
|
|
||||||
}
|
|
||||||
this.updateHeight(node); // 更新结点高度
|
|
||||||
/* 2. 执行旋转操作,使该子树重新恢复平衡 */
|
|
||||||
node = this.rotate(node);
|
|
||||||
// 返回子树的根结点
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "C"
|
=== "C"
|
||||||
@ -817,33 +730,9 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影
|
|||||||
=== "Swift"
|
=== "Swift"
|
||||||
|
|
||||||
```swift title="avl_tree.swift"
|
```swift title="avl_tree.swift"
|
||||||
/* 插入结点 */
|
[class]{AVLTree}-[func]{insert}
|
||||||
@discardableResult
|
|
||||||
func insert(val: Int) -> TreeNode? {
|
|
||||||
root = insertHelper(node: root, val: val)
|
|
||||||
return root
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 递归插入结点(辅助函数) */
|
[class]{AVLTree}-[func]{insertHelper}
|
||||||
func insertHelper(node: TreeNode?, val: Int) -> TreeNode? {
|
|
||||||
var node = node
|
|
||||||
if node == nil {
|
|
||||||
return TreeNode(x: val)
|
|
||||||
}
|
|
||||||
/* 1. 查找插入位置,并插入结点 */
|
|
||||||
if val < node!.val {
|
|
||||||
node?.left = insertHelper(node: node?.left, val: val)
|
|
||||||
} else if val > node!.val {
|
|
||||||
node?.right = insertHelper(node: node?.right, val: val)
|
|
||||||
} else {
|
|
||||||
return node // 重复结点不插入,直接返回
|
|
||||||
}
|
|
||||||
updateHeight(node: node) // 更新结点高度
|
|
||||||
/* 2. 执行旋转操作,使该子树重新恢复平衡 */
|
|
||||||
node = rotate(node: node)
|
|
||||||
// 返回子树的根结点
|
|
||||||
return node
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "Zig"
|
=== "Zig"
|
||||||
@ -869,56 +758,11 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影
|
|||||||
=== "C++"
|
=== "C++"
|
||||||
|
|
||||||
```cpp title="avl_tree.cpp"
|
```cpp title="avl_tree.cpp"
|
||||||
/* 删除结点 */
|
[class]{AVLTree}-[func]{remove}
|
||||||
TreeNode* remove(int val) {
|
|
||||||
root = removeHelper(root, val);
|
|
||||||
return root;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */
|
[class]{AVLTree}-[func]{removeHelper}
|
||||||
TreeNode* getInOrderNext(TreeNode* node) {
|
|
||||||
if (node == nullptr) return node;
|
|
||||||
// 循环访问左子结点,直到叶结点时为最小结点,跳出
|
|
||||||
while (node->left != nullptr) {
|
|
||||||
node = node->left;
|
|
||||||
}
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 递归删除结点(辅助函数) */
|
[class]{AVLTree}-[func]{getInOrderNext}
|
||||||
TreeNode* removeHelper(TreeNode* node, int val) {
|
|
||||||
if (node == nullptr) return nullptr;
|
|
||||||
/* 1. 查找结点,并删除之 */
|
|
||||||
if (val < node->val)
|
|
||||||
node->left = removeHelper(node->left, val);
|
|
||||||
else if (val > node->val)
|
|
||||||
node->right = removeHelper(node->right, val);
|
|
||||||
else {
|
|
||||||
if (node->left == nullptr || node->right == nullptr) {
|
|
||||||
TreeNode* child = node->left != nullptr ? node->left : node->right;
|
|
||||||
// 子结点数量 = 0 ,直接删除 node 并返回
|
|
||||||
if (child == nullptr) {
|
|
||||||
delete node;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
// 子结点数量 = 1 ,直接删除 node
|
|
||||||
else {
|
|
||||||
delete node;
|
|
||||||
node = child;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结点
|
|
||||||
TreeNode* temp = getInOrderNext(node->right);
|
|
||||||
node->right = removeHelper(node->right, temp->val);
|
|
||||||
node->val = temp->val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
updateHeight(node); // 更新结点高度
|
|
||||||
/* 2. 执行旋转操作,使该子树重新恢复平衡 */
|
|
||||||
node = rotate(node);
|
|
||||||
// 返回子树的根结点
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "Python"
|
=== "Python"
|
||||||
@ -927,6 +771,8 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影
|
|||||||
[class]{AVLTree}-[func]{remove}
|
[class]{AVLTree}-[func]{remove}
|
||||||
|
|
||||||
[class]{AVLTree}-[func]{__remove_helper}
|
[class]{AVLTree}-[func]{__remove_helper}
|
||||||
|
|
||||||
|
[class]{AVLTree}-[func]{__get_inorder_next}
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "Go"
|
=== "Go"
|
||||||
@ -992,100 +838,21 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影
|
|||||||
=== "JavaScript"
|
=== "JavaScript"
|
||||||
|
|
||||||
```javascript title="avl_tree.js"
|
```javascript title="avl_tree.js"
|
||||||
/* 删除结点 */
|
[class]{AVLTree}-[func]{remove}
|
||||||
remove(val) {
|
|
||||||
this.root = this.removeHelper(this.root, val);
|
|
||||||
return this.root;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 递归删除结点(辅助函数) */
|
[class]{AVLTree}-[func]{removeHelper}
|
||||||
removeHelper(node, val) {
|
|
||||||
if (node === null) return null;
|
|
||||||
/* 1. 查找结点,并删除之 */
|
|
||||||
if (val < node.val) node.left = this.removeHelper(node.left, val);
|
|
||||||
else if (val > node.val) node.right = this.removeHelper(node.right, val);
|
|
||||||
else {
|
|
||||||
if (node.left === null || node.right === null) {
|
|
||||||
const child = node.left !== null ? node.left : node.right;
|
|
||||||
// 子结点数量 = 0 ,直接删除 node 并返回
|
|
||||||
if (child === null) return null;
|
|
||||||
// 子结点数量 = 1 ,直接删除 node
|
|
||||||
else node = child;
|
|
||||||
} else {
|
|
||||||
// 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结点
|
|
||||||
const temp = this.getInOrderNext(node.right);
|
|
||||||
node.right = this.removeHelper(node.right, temp.val);
|
|
||||||
node.val = temp.val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.updateHeight(node); // 更新结点高度
|
|
||||||
/* 2. 执行旋转操作,使该子树重新恢复平衡 */
|
|
||||||
node = this.rotate(node);
|
|
||||||
// 返回子树的根结点
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */
|
[class]{AVLTree}-[func]{getInOrderNext}
|
||||||
getInOrderNext(node) {
|
|
||||||
if (node === null) return node;
|
|
||||||
// 循环访问左子结点,直到叶结点时为最小结点,跳出
|
|
||||||
while (node.left !== null) {
|
|
||||||
node = node.left;
|
|
||||||
}
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "TypeScript"
|
=== "TypeScript"
|
||||||
|
|
||||||
```typescript title="avl_tree.ts"
|
```typescript title="avl_tree.ts"
|
||||||
/* 删除结点 */
|
[class]{AVLTree}-[func]{remove}
|
||||||
remove(val: number): TreeNode {
|
|
||||||
this.root = this.removeHelper(this.root, val);
|
|
||||||
return this.root;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 递归删除结点(辅助函数) */
|
[class]{AVLTree}-[func]{removeHelper}
|
||||||
removeHelper(node: TreeNode, val: number): TreeNode {
|
|
||||||
if (node === null) return null;
|
|
||||||
/* 1. 查找结点,并删除之 */
|
|
||||||
if (val < node.val) {
|
|
||||||
node.left = this.removeHelper(node.left, val);
|
|
||||||
} else if (val > node.val) {
|
|
||||||
node.right = this.removeHelper(node.right, val);
|
|
||||||
} else {
|
|
||||||
if (node.left === null || node.right === null) {
|
|
||||||
const child = node.left !== null ? node.left : node.right;
|
|
||||||
// 子结点数量 = 0 ,直接删除 node 并返回
|
|
||||||
if (child === null) {
|
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
// 子结点数量 = 1 ,直接删除 node
|
|
||||||
node = child;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结点
|
|
||||||
const temp = this.getInOrderNext(node.right);
|
|
||||||
node.right = this.removeHelper(node.right, temp.val);
|
|
||||||
node.val = temp.val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.updateHeight(node); // 更新结点高度
|
|
||||||
/* 2. 执行旋转操作,使该子树重新恢复平衡 */
|
|
||||||
node = this.rotate(node);
|
|
||||||
// 返回子树的根结点
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */
|
[class]{AVLTree}-[func]{getInOrderNext}
|
||||||
getInOrderNext(node: TreeNode): TreeNode {
|
|
||||||
if (node === null) return node;
|
|
||||||
// 循环访问左子结点,直到叶结点时为最小结点,跳出
|
|
||||||
while (node.left !== null) {
|
|
||||||
node = node.left;
|
|
||||||
}
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "C"
|
=== "C"
|
||||||
@ -1107,61 +874,11 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影
|
|||||||
=== "Swift"
|
=== "Swift"
|
||||||
|
|
||||||
```swift title="avl_tree.swift"
|
```swift title="avl_tree.swift"
|
||||||
/* 删除结点 */
|
[class]{AVLTree}-[func]{remove}
|
||||||
@discardableResult
|
|
||||||
func remove(val: Int) -> TreeNode? {
|
|
||||||
root = removeHelper(node: root, val: val)
|
|
||||||
return root
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 递归删除结点(辅助函数) */
|
[class]{AVLTree}-[func]{removeHelper}
|
||||||
func removeHelper(node: TreeNode?, val: Int) -> TreeNode? {
|
|
||||||
var node = node
|
|
||||||
if node == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
/* 1. 查找结点,并删除之 */
|
|
||||||
if val < node!.val {
|
|
||||||
node?.left = removeHelper(node: node?.left, val: val)
|
|
||||||
} else if val > node!.val {
|
|
||||||
node?.right = removeHelper(node: node?.right, val: val)
|
|
||||||
} else {
|
|
||||||
if node?.left == nil || node?.right == nil {
|
|
||||||
let child = node?.left != nil ? node?.left : node?.right
|
|
||||||
// 子结点数量 = 0 ,直接删除 node 并返回
|
|
||||||
if child == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
// 子结点数量 = 1 ,直接删除 node
|
|
||||||
else {
|
|
||||||
node = child
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结点
|
|
||||||
let temp = getInOrderNext(node: node?.right)
|
|
||||||
node?.right = removeHelper(node: node?.right, val: temp!.val)
|
|
||||||
node?.val = temp!.val
|
|
||||||
}
|
|
||||||
}
|
|
||||||
updateHeight(node: node) // 更新结点高度
|
|
||||||
/* 2. 执行旋转操作,使该子树重新恢复平衡 */
|
|
||||||
node = rotate(node: node)
|
|
||||||
// 返回子树的根结点
|
|
||||||
return node
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */
|
[class]{AVLTree}-[func]{getInOrderNext}
|
||||||
private func getInOrderNext(node: TreeNode?) -> TreeNode? {
|
|
||||||
var node = node
|
|
||||||
if node == nil {
|
|
||||||
return node
|
|
||||||
}
|
|
||||||
// 循环访问左子结点,直到叶结点时为最小结点,跳出
|
|
||||||
while node?.left != nil {
|
|
||||||
node = node?.left
|
|
||||||
}
|
|
||||||
return node
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "Zig"
|
=== "Zig"
|
||||||
|
Loading…
Reference in New Issue
Block a user