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
+30 -30
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">
@@ -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>
@@ -1888,7 +1888,7 @@
<span class="md-ellipsis">
7.3 Array Representation of Tree
7.3 Array Representation of Binary Trees
@@ -2107,7 +2107,7 @@
<span class="md-ellipsis">
8.2 Building a Heap
8.2 Heap Construction Operation
@@ -2135,7 +2135,7 @@
<span class="md-ellipsis">
8.3 Top-K Problem
8.3 Top-k Problem
@@ -2493,7 +2493,7 @@
<span class="md-ellipsis">
10.2 Binary Search Insertion
10.2 Binary Search Insertion Point
@@ -2521,7 +2521,7 @@
<span class="md-ellipsis">
10.3 Binary Search Edge Cases
10.3 Binary Search Boundaries
@@ -2577,7 +2577,7 @@
<span class="md-ellipsis">
10.5 Search Algorithms Revisited
10.5 Searching Algorithms Revisited
@@ -2728,7 +2728,7 @@
<span class="md-ellipsis">
11.1 Sorting Algorithms
11.1 Sorting Algorithm
@@ -3282,7 +3282,7 @@
<span class="md-ellipsis">
12.4 Hanoi Tower Problem
12.4 Hanota Problem
@@ -4194,7 +4194,7 @@
<span class="md-ellipsis">
16.3 Terminology Table
16.3 Glossary
@@ -4379,16 +4379,16 @@
<!-- Page content -->
<h1 id="114-insertion-sort">11.4 &nbsp; Insertion Sort<a class="headerlink" href="#114-insertion-sort" title="Permanent link">&para;</a></h1>
<p><u>Insertion sort (insertion sort)</u> is a simple sorting algorithm that works very similarly to the process of manually organizing a deck of cards.</p>
<p>Specifically, we select a base element from the unsorted interval, compare the element with elements in the sorted interval to its left one by one, and insert the element into the correct position.</p>
<p>Figure 11-6 shows the operation flow of inserting an element into the array. Let the base element be <code>base</code>. We need to move all elements from the target index to <code>base</code> one position to the right, and then assign <code>base</code> to the target index.</p>
<p><u>Insertion sort</u> is a simple sorting algorithm that works very similarly to the process of manually sorting a deck of cards.</p>
<p>Specifically, we select a base element from the unsorted portion, compare it one by one with the elements in the sorted portion to its left, and insert it into the correct position.</p>
<p>Figure 11-6 illustrates how an element is inserted into an array. Let the base element be <code>base</code>. We need to shift all elements between the target index and <code>base</code> one position to the right, and then assign <code>base</code> to the target index.</p>
<p><img alt="Single insertion operation" class="animation-figure" src="../insertion_sort.assets/insertion_operation.png" /></p>
<p align="center"> Figure 11-6 &nbsp; Single insertion operation </p>
<h2 id="1141-algorithm-flow">11.4.1 &nbsp; Algorithm Flow<a class="headerlink" href="#1141-algorithm-flow" title="Permanent link">&para;</a></h2>
<p>The overall flow of insertion sort is shown in Figure 11-7.</p>
<ol>
<li>Initially, the first element of the array has completed sorting.</li>
<li>Initially, the first element of the array is already sorted.</li>
<li>Select the second element of the array as <code>base</code>, and after inserting it into the correct position, <strong>the first 2 elements of the array are sorted</strong>.</li>
<li>Select the third element as <code>base</code>, and after inserting it into the correct position, <strong>the first 3 elements of the array are sorted</strong>.</li>
<li>And so on. In the last round, select the last element as <code>base</code>, and after inserting it into the correct position, <strong>all elements are sorted</strong>.</li>
@@ -4618,17 +4618,17 @@
</div>
<h2 id="1142-algorithm-characteristics">11.4.2 &nbsp; Algorithm Characteristics<a class="headerlink" href="#1142-algorithm-characteristics" title="Permanent link">&para;</a></h2>
<ul>
<li><strong>Time complexity of <span class="arithmatex">\(O(n^2)\)</span>, adaptive sorting</strong>: In the worst case, each insertion operation requires loops of <span class="arithmatex">\(n - 1\)</span>, <span class="arithmatex">\(n-2\)</span>, <span class="arithmatex">\(\dots\)</span>, <span class="arithmatex">\(2\)</span>, <span class="arithmatex">\(1\)</span>, summing to <span class="arithmatex">\((n - 1) n / 2\)</span>, so the time complexity is <span class="arithmatex">\(O(n^2)\)</span>. When encountering ordered data, the insertion operation will terminate early. When the input array is completely ordered, insertion sort achieves the best-case time complexity of <span class="arithmatex">\(O(n)\)</span>.</li>
<li><strong>Time complexity of <span class="arithmatex">\(O(n^2)\)</span>, adaptive sorting</strong>: In the worst case, the insertion operations require <span class="arithmatex">\(n - 1\)</span>, <span class="arithmatex">\(n-2\)</span>, <span class="arithmatex">\(\dots\)</span>, <span class="arithmatex">\(2\)</span>, and <span class="arithmatex">\(1\)</span> iterations, respectively, summing to <span class="arithmatex">\((n - 1) n / 2\)</span>, so the time complexity is <span class="arithmatex">\(O(n^2)\)</span>. When the data is already sorted, each insertion operation terminates early. When the input array is completely sorted, insertion sort achieves its best-case time complexity of <span class="arithmatex">\(O(n)\)</span>.</li>
<li><strong>Space complexity of <span class="arithmatex">\(O(1)\)</span>, in-place sorting</strong>: Pointers <span class="arithmatex">\(i\)</span> and <span class="arithmatex">\(j\)</span> use a constant amount of extra space.</li>
<li><strong>Stable sorting</strong>: During the insertion operation process, we insert elements to the right of equal elements, without changing their order.</li>
<li><strong>Stable sorting</strong>: During insertion, we place elements to the right of equal elements, so their relative order is unchanged.</li>
</ul>
<h2 id="1143-advantages-of-insertion-sort">11.4.3 &nbsp; Advantages of Insertion Sort<a class="headerlink" href="#1143-advantages-of-insertion-sort" title="Permanent link">&para;</a></h2>
<p>The time complexity of insertion sort is <span class="arithmatex">\(O(n^2)\)</span>, while the time complexity of quick sort, which we will learn about next, is <span class="arithmatex">\(O(n \log n)\)</span>. Although insertion sort has a higher time complexity, <strong>insertion sort is usually faster for smaller data volumes</strong>.</p>
<p>This conclusion is similar to the applicable situations of linear search and binary search. Algorithms like quick sort with <span class="arithmatex">\(O(n \log n)\)</span> complexity are sorting algorithms based on divide-and-conquer strategy and often contain more unit computation operations. When the data volume is small, <span class="arithmatex">\(n^2\)</span> and <span class="arithmatex">\(n \log n\)</span> are numerically close, and complexity does not dominate; the number of unit operations per round plays a decisive role.</p>
<p>In fact, the built-in sorting functions in many programming languages (such as Java) adopt insertion sort. The general approach is: for long arrays, use sorting algorithms based on divide-and-conquer strategy, such as quick sort; for short arrays, directly use insertion sort.</p>
<p>The time complexity of insertion sort is <span class="arithmatex">\(O(n^2)\)</span>, while the time complexity of quick sort, which we will learn about next, is <span class="arithmatex">\(O(n \log n)\)</span>. Although insertion sort has a higher time complexity, <strong>it is usually faster on small datasets</strong>.</p>
<p>This conclusion is similar to the one about when linear search and binary search are applicable. Algorithms such as quick sort, with <span class="arithmatex">\(O(n \log n)\)</span> complexity, are divide-and-conquer sorting algorithms and often involve more primitive operations. When the dataset is small, the values of <span class="arithmatex">\(n^2\)</span> and <span class="arithmatex">\(n \log n\)</span> are relatively close, so asymptotic complexity does not dominate; instead, the number of primitive operations per round becomes the deciding factor.</p>
<p>In fact, the built-in sorting functions of many programming languages (such as Java) use insertion sort. The general idea is: for large arrays, use divide-and-conquer sorting algorithms such as quick sort; for short arrays, use insertion sort directly.</p>
<p>Although bubble sort, selection sort, and insertion sort all have a time complexity of <span class="arithmatex">\(O(n^2)\)</span>, in actual situations, <strong>insertion sort is used significantly more frequently than bubble sort and selection sort</strong>, mainly for the following reasons.</p>
<ul>
<li>Bubble sort is based on element swapping, requiring the use of a temporary variable, involving 3 unit operations; insertion sort is based on element assignment, requiring only 1 unit operation. Therefore, <strong>the computational overhead of bubble sort is usually higher than that of insertion sort</strong>.</li>
<li>Bubble sort is implemented through element swaps, which require a temporary variable and involve 3 primitive operations; insertion sort is implemented through element assignment and requires only 1 primitive operation. Therefore, <strong>bubble sort usually has higher computational overhead than insertion sort</strong>.</li>
<li>Selection sort has a time complexity of <span class="arithmatex">\(O(n^2)\)</span> in any case. <strong>If given a set of partially ordered data, insertion sort is usually more efficient than selection sort</strong>.</li>
<li>Selection sort is unstable and cannot be applied to multi-level sorting.</li>
</ul>