This commit is contained in:
krahets
2026-04-02 03:08:50 +08:00
parent 09a136c9fa
commit aaf9f58eb3
157 changed files with 3002 additions and 2994 deletions
+44 -44
View File
@@ -6,7 +6,7 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="description" content="Data Structures and Algorithms Crash Course with Animated Illustrations and Off-the-Shelf Code">
<meta name="description" content="Data structures and algorithms tutorial with animated illustrations and ready-to-run code">
<meta name="author" content="krahets">
@@ -39,7 +39,7 @@
<title>7.5 Avl Tree * - Hello Algo</title>
<title>7.5 AVL Tree * - Hello Algo</title>
@@ -154,7 +154,7 @@
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
7.5 &nbsp; Avl Tree *
7.5 &nbsp; AVL Tree *
</span>
</div>
@@ -576,7 +576,7 @@
<span class="md-ellipsis">
Chapter 1. Encounter With Algorithms
Chapter 1. Encounter with Algorithms
@@ -598,7 +598,7 @@
<span class="md-nav__icon md-icon"></span>
Chapter 1. Encounter With Algorithms
Chapter 1. Encounter with Algorithms
</label>
@@ -1183,7 +1183,7 @@
<span class="md-ellipsis">
Chapter 4. Array and Linked List
Chapter 4. Arrays and Linked Lists
@@ -1205,7 +1205,7 @@
<span class="md-nav__icon md-icon"></span>
Chapter 4. Array and Linked List
Chapter 4. Arrays and Linked Lists
</label>
@@ -1311,7 +1311,7 @@
<span class="md-ellipsis">
4.4 Memory and Cache *
4.4 Random-Access Memory and Cache *
@@ -1402,7 +1402,7 @@
<span class="md-ellipsis">
Chapter 5. Stack and Queue
Chapter 5. Stacks and Queues
@@ -1424,7 +1424,7 @@
<span class="md-nav__icon md-icon"></span>
Chapter 5. Stack and Queue
Chapter 5. Stacks and Queues
</label>
@@ -1502,7 +1502,7 @@
<span class="md-ellipsis">
5.3 Double-Ended Queue
5.3 Deque
@@ -1593,7 +1593,7 @@
<span class="md-ellipsis">
Chapter 6. Hashing
Chapter 6. Hash Table
@@ -1615,7 +1615,7 @@
<span class="md-nav__icon md-icon"></span>
Chapter 6. Hashing
Chapter 6. Hash Table
</label>
@@ -1890,7 +1890,7 @@
<span class="md-ellipsis">
7.3 Array Representation of Tree
7.3 Array Representation of Binary Trees
@@ -2003,12 +2003,12 @@
<a href="#751-common-terminology-in-avl-trees" class="md-nav__link">
<span class="md-ellipsis">
7.5.1 &nbsp; Common Terminology in Avl Trees
7.5.1 &nbsp; Common Terminology in AVL Trees
</span>
</a>
<nav class="md-nav" aria-label="7.5.1 Common Terminology in Avl Trees">
<nav class="md-nav" aria-label="7.5.1 Common Terminology in AVL Trees">
<ul class="md-nav__list">
<li class="md-nav__item">
@@ -2042,12 +2042,12 @@
<a href="#752-rotations-in-avl-trees" class="md-nav__link">
<span class="md-ellipsis">
7.5.2 &nbsp; Rotations in Avl Trees
7.5.2 &nbsp; Rotations in AVL Trees
</span>
</a>
<nav class="md-nav" aria-label="7.5.2 Rotations in Avl Trees">
<nav class="md-nav" aria-label="7.5.2 Rotations in AVL Trees">
<ul class="md-nav__list">
<li class="md-nav__item">
@@ -2114,12 +2114,12 @@
<a href="#753-common-operations-in-avl-trees" class="md-nav__link">
<span class="md-ellipsis">
7.5.3 &nbsp; Common Operations in Avl Trees
7.5.3 &nbsp; Common Operations in AVL Trees
</span>
</a>
<nav class="md-nav" aria-label="7.5.3 Common Operations in Avl Trees">
<nav class="md-nav" aria-label="7.5.3 Common Operations in AVL Trees">
<ul class="md-nav__list">
<li class="md-nav__item">
@@ -2164,7 +2164,7 @@
<a href="#754-typical-applications-of-avl-trees" class="md-nav__link">
<span class="md-ellipsis">
7.5.4 &nbsp; Typical Applications of Avl Trees
7.5.4 &nbsp; Typical Applications of AVL Trees
</span>
</a>
@@ -2329,7 +2329,7 @@
<span class="md-ellipsis">
8.2 Building a Heap
8.2 Heap Construction Operation
@@ -2357,7 +2357,7 @@
<span class="md-ellipsis">
8.3 Top-K Problem
8.3 Top-k Problem
@@ -2715,7 +2715,7 @@
<span class="md-ellipsis">
10.2 Binary Search Insertion
10.2 Binary Search Insertion Point
@@ -2743,7 +2743,7 @@
<span class="md-ellipsis">
10.3 Binary Search Edge Cases
10.3 Binary Search Boundaries
@@ -2799,7 +2799,7 @@
<span class="md-ellipsis">
10.5 Search Algorithms Revisited
10.5 Searching Algorithms Revisited
@@ -2948,7 +2948,7 @@
<span class="md-ellipsis">
11.1 Sorting Algorithms
11.1 Sorting Algorithm
@@ -3421,7 +3421,7 @@
<span class="md-ellipsis">
12.4 Hanoi Tower Problem
12.4 Hanota Problem
@@ -4333,7 +4333,7 @@
<span class="md-ellipsis">
16.3 Terminology Table
16.3 Glossary
@@ -4451,12 +4451,12 @@
<a href="#751-common-terminology-in-avl-trees" class="md-nav__link">
<span class="md-ellipsis">
7.5.1 &nbsp; Common Terminology in Avl Trees
7.5.1 &nbsp; Common Terminology in AVL Trees
</span>
</a>
<nav class="md-nav" aria-label="7.5.1 Common Terminology in Avl Trees">
<nav class="md-nav" aria-label="7.5.1 Common Terminology in AVL Trees">
<ul class="md-nav__list">
<li class="md-nav__item">
@@ -4490,12 +4490,12 @@
<a href="#752-rotations-in-avl-trees" class="md-nav__link">
<span class="md-ellipsis">
7.5.2 &nbsp; Rotations in Avl Trees
7.5.2 &nbsp; Rotations in AVL Trees
</span>
</a>
<nav class="md-nav" aria-label="7.5.2 Rotations in Avl Trees">
<nav class="md-nav" aria-label="7.5.2 Rotations in AVL Trees">
<ul class="md-nav__list">
<li class="md-nav__item">
@@ -4562,12 +4562,12 @@
<a href="#753-common-operations-in-avl-trees" class="md-nav__link">
<span class="md-ellipsis">
7.5.3 &nbsp; Common Operations in Avl Trees
7.5.3 &nbsp; Common Operations in AVL Trees
</span>
</a>
<nav class="md-nav" aria-label="7.5.3 Common Operations in Avl Trees">
<nav class="md-nav" aria-label="7.5.3 Common Operations in AVL Trees">
<ul class="md-nav__list">
<li class="md-nav__item">
@@ -4612,7 +4612,7 @@
<a href="#754-typical-applications-of-avl-trees" class="md-nav__link">
<span class="md-ellipsis">
7.5.4 &nbsp; Typical Applications of Avl Trees
7.5.4 &nbsp; Typical Applications of AVL Trees
</span>
</a>
@@ -4656,7 +4656,7 @@
<!-- Page content -->
<h1 id="75-avl-tree">7.5 &nbsp; Avl Tree *<a class="headerlink" href="#75-avl-tree" title="Permanent link">&para;</a></h1>
<h1 id="75-avl-tree">7.5 &nbsp; AVL Tree *<a class="headerlink" href="#75-avl-tree" title="Permanent link">&para;</a></h1>
<p>In the "Binary Search Tree" section, we mentioned that after multiple insertion and removal operations, a binary search tree may degenerate into a linked list. In this case, the time complexity of all operations degrades from <span class="arithmatex">\(O(\log n)\)</span> to <span class="arithmatex">\(O(n)\)</span>.</p>
<p>As shown in Figure 7-24, after two node removal operations, this binary search tree will degrade into a linked list.</p>
<p><img alt="Degradation of an AVL tree after removing nodes" class="animation-figure" src="../avl_tree.assets/avltree_degradation_from_removing_node.png" /></p>
@@ -4666,8 +4666,8 @@
<p><img alt="Degradation of an AVL tree after inserting nodes" class="animation-figure" src="../avl_tree.assets/avltree_degradation_from_inserting_node.png" /></p>
<p align="center"> Figure 7-25 &nbsp; Degradation of an AVL tree after inserting nodes </p>
<p>In 1962, G. M. Adelson-Velsky and E. M. Landis proposed the <u>AVL tree</u> in their paper "An algorithm for the organization of information". The paper described in detail a series of operations ensuring that after continuously adding and removing nodes, the AVL tree does not degenerate, thus keeping the time complexity of various operations at the <span class="arithmatex">\(O(\log n)\)</span> level. In other words, in scenarios requiring frequent insertions, deletions, searches, and modifications, the AVL tree can always maintain efficient data operation performance, making it very valuable in applications.</p>
<h2 id="751-common-terminology-in-avl-trees">7.5.1 &nbsp; Common Terminology in Avl Trees<a class="headerlink" href="#751-common-terminology-in-avl-trees" title="Permanent link">&para;</a></h2>
<p>In 1962, G. M. Adelson-Velsky and E. M. Landis proposed the <u>AVL tree</u> in their paper "An algorithm for the organization of information". The paper describes a series of operations that prevent an AVL tree from degenerating as nodes are inserted and removed, thereby keeping the time complexity of various operations at <span class="arithmatex">\(O(\log n)\)</span>. In other words, in scenarios that require frequent insertion, deletion, lookup, and update operations, AVL trees can maintain consistently efficient performance and therefore have strong practical value.</p>
<h2 id="751-common-terminology-in-avl-trees">7.5.1 &nbsp; Common Terminology in AVL Trees<a class="headerlink" href="#751-common-terminology-in-avl-trees" title="Permanent link">&para;</a></h2>
<p>An AVL tree is both a binary search tree and a balanced binary tree, simultaneously satisfying all the properties of these two types of binary trees, hence it is a <u>balanced binary search tree</u>.</p>
<h3 id="1-node-height">1. &nbsp; Node Height<a class="headerlink" href="#1-node-height" title="Permanent link">&para;</a></h3>
<p>Since the operations related to AVL trees require obtaining node heights, we need to add a <code>height</code> variable to the node class:</p>
@@ -4857,7 +4857,7 @@
</div>
</div>
</div>
<p>The "node height" refers to the distance from that node to its farthest leaf node, i.e., the number of "edges" passed. It is important to note that the height of a leaf node is <span class="arithmatex">\(0\)</span>, and the height of a null node is <span class="arithmatex">\(-1\)</span>. We will create two utility functions for getting and updating the height of a node:</p>
<p>The "node height" refers to the distance from that node to its farthest leaf node, i.e., the number of edges on the path. It is important to note that the height of a leaf node is <span class="arithmatex">\(0\)</span>, and the height of a null node is <span class="arithmatex">\(-1\)</span>. We will create two utility functions for getting and updating the height of a node:</p>
<div class="tabbed-set tabbed-alternate" data-tabs="2:13"><input checked="checked" id="__tabbed_2_1" name="__tabbed_2" type="radio" /><input id="__tabbed_2_2" name="__tabbed_2" type="radio" /><input id="__tabbed_2_3" name="__tabbed_2" type="radio" /><input id="__tabbed_2_4" name="__tabbed_2" type="radio" /><input id="__tabbed_2_5" name="__tabbed_2" type="radio" /><input id="__tabbed_2_6" name="__tabbed_2" type="radio" /><input id="__tabbed_2_7" name="__tabbed_2" type="radio" /><input id="__tabbed_2_8" name="__tabbed_2" type="radio" /><input id="__tabbed_2_9" name="__tabbed_2" type="radio" /><input id="__tabbed_2_10" name="__tabbed_2" type="radio" /><input id="__tabbed_2_11" name="__tabbed_2" type="radio" /><input id="__tabbed_2_12" name="__tabbed_2" type="radio" /><input id="__tabbed_2_13" name="__tabbed_2" type="radio" /><div class="tabbed-labels"><label for="__tabbed_2_1">Python</label><label for="__tabbed_2_2">C++</label><label for="__tabbed_2_3">Java</label><label for="__tabbed_2_4">C#</label><label for="__tabbed_2_5">Go</label><label for="__tabbed_2_6">Swift</label><label for="__tabbed_2_7">JS</label><label for="__tabbed_2_8">TS</label><label for="__tabbed_2_9">Dart</label><label for="__tabbed_2_10">Rust</label><label for="__tabbed_2_11">C</label><label for="__tabbed_2_12">Kotlin</label><label for="__tabbed_2_13">Ruby</label></div>
<div class="tabbed-content">
<div class="tabbed-block">
@@ -5224,9 +5224,9 @@
<p class="admonition-title">Tip</p>
<p>Let the balance factor be <span class="arithmatex">\(f\)</span>, then the balance factor of any node in an AVL tree satisfies <span class="arithmatex">\(-1 \le f \le 1\)</span>.</p>
</div>
<h2 id="752-rotations-in-avl-trees">7.5.2 &nbsp; Rotations in Avl Trees<a class="headerlink" href="#752-rotations-in-avl-trees" title="Permanent link">&para;</a></h2>
<h2 id="752-rotations-in-avl-trees">7.5.2 &nbsp; Rotations in AVL Trees<a class="headerlink" href="#752-rotations-in-avl-trees" title="Permanent link">&para;</a></h2>
<p>The characteristic of AVL trees lies in the "rotation" operation, which can restore balance to unbalanced nodes without affecting the inorder traversal sequence of the binary tree. In other words, <strong>rotation operations can both maintain the property of a "binary search tree" and make the tree return to a "balanced binary tree"</strong>.</p>
<p>We call nodes with a balance factor absolute value <span class="arithmatex">\(&gt; 1\)</span> "unbalanced nodes". Depending on the imbalance situation, rotation operations are divided into four types: right rotation, left rotation, left rotation then right rotation, and right rotation then left rotation. Below we describe these rotation operations in detail.</p>
<p>We call nodes with a balance factor absolute value <span class="arithmatex">\(&gt; 1\)</span> "unbalanced nodes". Depending on the imbalance situation, rotation operations are divided into four types: right rotation, left rotation, right rotation then left rotation, and left rotation then right rotation. Below we describe these rotation operations in detail.</p>
<h3 id="1-right-rotation">1. &nbsp; Right Rotation<a class="headerlink" href="#1-right-rotation" title="Permanent link">&para;</a></h3>
<p>As shown in Figure 7-26, the value below the node is the balance factor. From bottom to top, the first unbalanced node in the binary tree is "node 3". We focus on the subtree with this unbalanced node as the root, denoting the node as <code>node</code> and its left child as <code>child</code>, and perform a "right rotation" operation. After the right rotation is completed, the subtree regains balance and still maintains the properties of a binary search tree.</p>
<div class="tabbed-set tabbed-alternate" data-tabs="4:4"><input checked="checked" id="__tabbed_4_1" name="__tabbed_4" type="radio" /><input id="__tabbed_4_2" name="__tabbed_4" type="radio" /><input id="__tabbed_4_3" name="__tabbed_4" type="radio" /><input id="__tabbed_4_4" name="__tabbed_4" type="radio" /><div class="tabbed-labels"><label for="__tabbed_4_1">&lt;1&gt;</label><label for="__tabbed_4_2">&lt;2&gt;</label><label for="__tabbed_4_3">&lt;3&gt;</label><label for="__tabbed_4_4">&lt;4&gt;</label></div>
@@ -6168,7 +6168,7 @@
</div>
</div>
</div>
<h2 id="753-common-operations-in-avl-trees">7.5.3 &nbsp; Common Operations in Avl Trees<a class="headerlink" href="#753-common-operations-in-avl-trees" title="Permanent link">&para;</a></h2>
<h2 id="753-common-operations-in-avl-trees">7.5.3 &nbsp; Common Operations in AVL Trees<a class="headerlink" href="#753-common-operations-in-avl-trees" title="Permanent link">&para;</a></h2>
<h3 id="1-node-insertion">1. &nbsp; Node Insertion<a class="headerlink" href="#1-node-insertion" title="Permanent link">&para;</a></h3>
<p>The node insertion operation in AVL trees is similar in principle to that in binary search trees. The only difference is that after inserting a node in an AVL tree, a series of unbalanced nodes may appear on the path from that node to the root. Therefore, <strong>we need to start from this node and perform rotation operations from bottom to top, restoring balance to all unbalanced nodes</strong>. The code is as follows:</p>
<div class="tabbed-set tabbed-alternate" data-tabs="8:13"><input checked="checked" id="__tabbed_8_1" name="__tabbed_8" type="radio" /><input id="__tabbed_8_2" name="__tabbed_8" type="radio" /><input id="__tabbed_8_3" name="__tabbed_8" type="radio" /><input id="__tabbed_8_4" name="__tabbed_8" type="radio" /><input id="__tabbed_8_5" name="__tabbed_8" type="radio" /><input id="__tabbed_8_6" name="__tabbed_8" type="radio" /><input id="__tabbed_8_7" name="__tabbed_8" type="radio" /><input id="__tabbed_8_8" name="__tabbed_8" type="radio" /><input id="__tabbed_8_9" name="__tabbed_8" type="radio" /><input id="__tabbed_8_10" name="__tabbed_8" type="radio" /><input id="__tabbed_8_11" name="__tabbed_8" type="radio" /><input id="__tabbed_8_12" name="__tabbed_8" type="radio" /><input id="__tabbed_8_13" name="__tabbed_8" type="radio" /><div class="tabbed-labels"><label for="__tabbed_8_1">Python</label><label for="__tabbed_8_2">C++</label><label for="__tabbed_8_3">Java</label><label for="__tabbed_8_4">C#</label><label for="__tabbed_8_5">Go</label><label for="__tabbed_8_6">Swift</label><label for="__tabbed_8_7">JS</label><label for="__tabbed_8_8">TS</label><label for="__tabbed_8_9">Dart</label><label for="__tabbed_8_10">Rust</label><label for="__tabbed_8_11">C</label><label for="__tabbed_8_12">Kotlin</label><label for="__tabbed_8_13">Ruby</label></div>
@@ -7100,7 +7100,7 @@
</div>
<h3 id="3-node-search">3. &nbsp; Node Search<a class="headerlink" href="#3-node-search" title="Permanent link">&para;</a></h3>
<p>The node search operation in AVL trees is consistent with that in binary search trees, and will not be elaborated here.</p>
<h2 id="754-typical-applications-of-avl-trees">7.5.4 &nbsp; Typical Applications of Avl Trees<a class="headerlink" href="#754-typical-applications-of-avl-trees" title="Permanent link">&para;</a></h2>
<h2 id="754-typical-applications-of-avl-trees">7.5.4 &nbsp; Typical Applications of AVL Trees<a class="headerlink" href="#754-typical-applications-of-avl-trees" title="Permanent link">&para;</a></h2>
<ul>
<li>Organizing and storing large-scale data, suitable for scenarios with high-frequency searches and low-frequency insertions and deletions.</li>
<li>Used to build index systems in databases.</li>