This commit is contained in:
krahets
2025-12-31 19:38:45 +08:00
parent fdc032e300
commit f31cbc3f9f
474 changed files with 130810 additions and 103691 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -37,7 +37,7 @@
<title>Chapter 4.   Arrays and linked lists - Hello Algo</title>
<title>Chapter 4.   Array and Linked List - Hello Algo</title>
@@ -58,8 +58,8 @@
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Lato:300,300i,400,400i,700,700i%7CJetBrains+Mono:400,400i,700,700i&display=fallback">
<style>:root{--md-text-font:"Lato";--md-code-font:"JetBrains Mono"}</style>
@@ -99,7 +99,7 @@
<div data-md-component="skip">
<a href="#chapter-4-arrays-and-linked-lists" class="md-skip">
<a href="#chapter-4-array-and-linked-list" class="md-skip">
Skip to content
</a>
@@ -154,7 +154,7 @@
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
Chapter 4. &nbsp; Arrays and linked lists
Chapter 4. &nbsp; Array and Linked List
</span>
</div>
@@ -371,7 +371,7 @@
<span class="md-ellipsis">
Before starting
Before Starting
@@ -388,7 +388,7 @@
<span class="md-nav__icon md-icon"></span>
Before starting
Before Starting
</label>
@@ -487,7 +487,7 @@
<span class="md-ellipsis">
0.1 About this book
0.1 About This Book
@@ -515,7 +515,7 @@
<span class="md-ellipsis">
0.2 How to read
0.2 How to Use This Book
@@ -604,7 +604,7 @@
<span class="md-ellipsis">
Chapter 1. Encounter with algorithms
Chapter 1. Encounter With Algorithms
@@ -626,7 +626,7 @@
<span class="md-nav__icon md-icon"></span>
Chapter 1. Encounter with algorithms
Chapter 1. Encounter With Algorithms
</label>
@@ -648,7 +648,7 @@
<span class="md-ellipsis">
1.1 Algorithms are everywhere
1.1 Algorithms Are Everywhere
@@ -676,7 +676,7 @@
<span class="md-ellipsis">
1.2 What is an algorithm
1.2 What Is an Algorithm
@@ -769,7 +769,7 @@
<span class="md-ellipsis">
Chapter 2. Complexity analysis
Chapter 2. Complexity Analysis
@@ -791,7 +791,7 @@
<span class="md-nav__icon md-icon"></span>
Chapter 2. Complexity analysis
Chapter 2. Complexity Analysis
</label>
@@ -813,7 +813,7 @@
<span class="md-ellipsis">
2.1 Algorithm efficiency assessment
2.1 Algorithm Efficiency Evaluation
@@ -841,7 +841,7 @@
<span class="md-ellipsis">
2.2 Iteration and recursion
2.2 Iteration and Recursion
@@ -869,7 +869,7 @@
<span class="md-ellipsis">
2.3 Time complexity
2.3 Time Complexity
@@ -897,7 +897,7 @@
<span class="md-ellipsis">
2.4 Space complexity
2.4 Space Complexity
@@ -990,7 +990,7 @@
<span class="md-ellipsis">
Chapter 3. Data structures
Chapter 3. Data Structures
@@ -1012,7 +1012,7 @@
<span class="md-nav__icon md-icon"></span>
Chapter 3. Data structures
Chapter 3. Data Structures
</label>
@@ -1034,7 +1034,7 @@
<span class="md-ellipsis">
3.1 Classification of data structures
3.1 Classification of Data Structures
@@ -1062,7 +1062,7 @@
<span class="md-ellipsis">
3.2 Basic data types
3.2 Basic Data Types
@@ -1090,7 +1090,7 @@
<span class="md-ellipsis">
3.3 Number encoding *
3.3 Number Encoding *
@@ -1118,7 +1118,7 @@
<span class="md-ellipsis">
3.4 Character encoding *
3.4 Character Encoding *
@@ -1213,7 +1213,7 @@
<span class="md-ellipsis">
Chapter 4. Array and linked list
Chapter 4. Array and Linked List
@@ -1235,7 +1235,7 @@
<span class="md-nav__icon md-icon"></span>
Chapter 4. Array and linked list
Chapter 4. Array and Linked List
</label>
@@ -1285,7 +1285,7 @@
<span class="md-ellipsis">
4.2 Linked list
4.2 Linked List
@@ -1341,7 +1341,7 @@
<span class="md-ellipsis">
4.4 Memory and cache *
4.4 Memory and Cache *
@@ -1432,7 +1432,7 @@
<span class="md-ellipsis">
Chapter 5. Stack and queue
Chapter 5. Stack and Queue
@@ -1454,7 +1454,7 @@
<span class="md-nav__icon md-icon"></span>
Chapter 5. Stack and queue
Chapter 5. Stack and Queue
</label>
@@ -1532,7 +1532,7 @@
<span class="md-ellipsis">
5.3 Double-ended queue
5.3 Double-Ended Queue
@@ -1623,7 +1623,7 @@
<span class="md-ellipsis">
Chapter 6. Hash table
Chapter 6. Hashing
@@ -1645,7 +1645,7 @@
<span class="md-nav__icon md-icon"></span>
Chapter 6. Hash table
Chapter 6. Hashing
</label>
@@ -1667,7 +1667,7 @@
<span class="md-ellipsis">
6.1 Hash table
6.1 Hash Table
@@ -1695,7 +1695,7 @@
<span class="md-ellipsis">
6.2 Hash collision
6.2 Hash Collision
@@ -1723,7 +1723,7 @@
<span class="md-ellipsis">
6.3 Hash algorithm
6.3 Hash Algorithm
@@ -1862,7 +1862,7 @@
<span class="md-ellipsis">
7.1 Binary tree
7.1 Binary Tree
@@ -1890,7 +1890,7 @@
<span class="md-ellipsis">
7.2 Binary tree traversal
7.2 Binary Tree Traversal
@@ -1918,7 +1918,7 @@
<span class="md-ellipsis">
7.3 Array Representation of tree
7.3 Array Representation of Tree
@@ -1946,7 +1946,7 @@
<span class="md-ellipsis">
7.4 Binary Search tree
7.4 Binary Search Tree
@@ -1974,7 +1974,7 @@
<span class="md-ellipsis">
7.5 AVL tree *
7.5 AVL Tree *
@@ -2137,7 +2137,7 @@
<span class="md-ellipsis">
8.2 Building a heap
8.2 Building a Heap
@@ -2165,7 +2165,7 @@
<span class="md-ellipsis">
8.3 Top-k problem
8.3 Top-K Problem
@@ -2328,7 +2328,7 @@
<span class="md-ellipsis">
9.2 Basic graph operations
9.2 Basic Operations on Graphs
@@ -2356,7 +2356,7 @@
<span class="md-ellipsis">
9.3 Graph traversal
9.3 Graph Traversal
@@ -2495,7 +2495,7 @@
<span class="md-ellipsis">
10.1 Binary search
10.1 Binary Search
@@ -2523,7 +2523,7 @@
<span class="md-ellipsis">
10.2 Binary search insertion
10.2 Binary Search Insertion
@@ -2551,7 +2551,7 @@
<span class="md-ellipsis">
10.3 Binary search boundaries
10.3 Binary Search Edge Cases
@@ -2579,7 +2579,7 @@
<span class="md-ellipsis">
10.4 Hashing optimization strategies
10.4 Hash Optimization Strategy
@@ -2607,7 +2607,7 @@
<span class="md-ellipsis">
10.5 Search algorithms revisited
10.5 Search Algorithms Revisited
@@ -2756,7 +2756,7 @@
<span class="md-ellipsis">
11.1 Sorting algorithms
11.1 Sorting Algorithms
@@ -2784,7 +2784,7 @@
<span class="md-ellipsis">
11.2 Selection sort
11.2 Selection Sort
@@ -2812,7 +2812,7 @@
<span class="md-ellipsis">
11.3 Bubble sort
11.3 Bubble Sort
@@ -2840,7 +2840,7 @@
<span class="md-ellipsis">
11.4 Insertion sort
11.4 Insertion Sort
@@ -2868,7 +2868,7 @@
<span class="md-ellipsis">
11.5 Quick sort
11.5 Quick Sort
@@ -2896,7 +2896,7 @@
<span class="md-ellipsis">
11.6 Merge sort
11.6 Merge Sort
@@ -2924,7 +2924,7 @@
<span class="md-ellipsis">
11.7 Heap sort
11.7 Heap Sort
@@ -2952,7 +2952,7 @@
<span class="md-ellipsis">
11.8 Bucket sort
11.8 Bucket Sort
@@ -2980,7 +2980,7 @@
<span class="md-ellipsis">
11.9 Counting sort
11.9 Counting Sort
@@ -3008,7 +3008,7 @@
<span class="md-ellipsis">
11.10 Radix sort
11.10 Radix Sort
@@ -3101,7 +3101,7 @@
<span class="md-ellipsis">
Chapter 12. Divide and conquer
Chapter 12. Divide and Conquer
@@ -3123,7 +3123,7 @@
<span class="md-nav__icon md-icon"></span>
Chapter 12. Divide and conquer
Chapter 12. Divide and Conquer
</label>
@@ -3145,7 +3145,7 @@
<span class="md-ellipsis">
12.1 Divide and conquer algorithms
12.1 Divide and Conquer Algorithms
@@ -3173,7 +3173,7 @@
<span class="md-ellipsis">
12.2 Divide and conquer search strategy
12.2 Divide and Conquer Search Strategy
@@ -3201,7 +3201,7 @@
<span class="md-ellipsis">
12.3 Building binary tree problem
12.3 Building a Binary Tree Problem
@@ -3229,7 +3229,7 @@
<span class="md-ellipsis">
12.4 Tower of Hanoi Problem
12.4 Hanoi Tower Problem
@@ -3366,7 +3366,7 @@
<span class="md-ellipsis">
13.1 Backtracking algorithms
13.1 Backtracking Algorithm
@@ -3394,7 +3394,7 @@
<span class="md-ellipsis">
13.2 Permutation problem
13.2 Permutations Problem
@@ -3422,7 +3422,7 @@
<span class="md-ellipsis">
13.3 Subset sum problem
13.3 Subset-Sum Problem
@@ -3450,7 +3450,7 @@
<span class="md-ellipsis">
13.4 n queens problem
13.4 N-Queens Problem
@@ -3547,7 +3547,7 @@
<span class="md-ellipsis">
Chapter 14. Dynamic programming
Chapter 14. Dynamic Programming
@@ -3569,7 +3569,7 @@
<span class="md-nav__icon md-icon"></span>
Chapter 14. Dynamic programming
Chapter 14. Dynamic Programming
</label>
@@ -3591,7 +3591,7 @@
<span class="md-ellipsis">
14.1 Introduction to dynamic programming
14.1 Introduction to Dynamic Programming
@@ -3619,7 +3619,7 @@
<span class="md-ellipsis">
14.2 Characteristics of DP problems
14.2 Characteristics of Dynamic Programming Problems
@@ -3647,7 +3647,7 @@
<span class="md-ellipsis">
14.3 DP problem-solving approach
14.3 Dynamic Programming Problem-Solving Approach
@@ -3675,7 +3675,7 @@
<span class="md-ellipsis">
14.4 0-1 Knapsack problem
14.4 0-1 Knapsack Problem
@@ -3703,7 +3703,7 @@
<span class="md-ellipsis">
14.5 Unbounded knapsack problem
14.5 Unbounded Knapsack Problem
@@ -3731,7 +3731,7 @@
<span class="md-ellipsis">
14.6 Edit distance problem
14.6 Edit Distance Problem
@@ -3868,7 +3868,7 @@
<span class="md-ellipsis">
15.1 Greedy algorithms
15.1 Greedy Algorithm
@@ -3896,7 +3896,7 @@
<span class="md-ellipsis">
15.2 Fractional knapsack problem
15.2 Fractional Knapsack Problem
@@ -3924,7 +3924,7 @@
<span class="md-ellipsis">
15.3 Maximum capacity problem
15.3 Maximum Capacity Problem
@@ -3952,7 +3952,7 @@
<span class="md-ellipsis">
15.4 Maximum product cutting problem
15.4 Maximum Product Cutting Problem
@@ -4085,7 +4085,7 @@
<span class="md-ellipsis">
16.1 Installation
16.1 Programming Environment Installation
@@ -4113,7 +4113,7 @@
<span class="md-ellipsis">
16.2 Contributing
16.2 Contributing Together
@@ -4141,7 +4141,7 @@
<span class="md-ellipsis">
16.3 Terminology
16.3 Terminology Table
@@ -4302,19 +4302,19 @@
<!-- Page content -->
<h1 id="chapter-4-arrays-and-linked-lists">Chapter 4. &nbsp; Arrays and linked lists<a class="headerlink" href="#chapter-4-arrays-and-linked-lists" title="Permanent link">&para;</a></h1>
<p><a class="glightbox" href="../assets/covers/chapter_array_and_linkedlist.jpg" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="Arrays and linked lists" class="cover-image" src="../assets/covers/chapter_array_and_linkedlist.jpg" /></a></p>
<h1 id="chapter-4-array-and-linked-list">Chapter 4. &nbsp; Array and Linked List<a class="headerlink" href="#chapter-4-array-and-linked-list" title="Permanent link">&para;</a></h1>
<p><a class="glightbox" href="../assets/covers/chapter_array_and_linkedlist.jpg" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="Array and Linked List" class="cover-image" src="../assets/covers/chapter_array_and_linkedlist.jpg" /></a></p>
<div class="admonition abstract">
<p class="admonition-title">Abstract</p>
<p>The world of data structures resembles a sturdy brick wall.</p>
<p>In arrays, envision bricks snugly aligned, each resting seamlessly beside the next, creating a unified formation. Meanwhile, in linked lists, these bricks disperse freely, embraced by vines gracefully knitting connections between them.</p>
<p>The world of data structures is like a solid brick wall.</p>
<p>Array bricks are neatly arranged, tightly packed one by one. Linked list bricks are scattered everywhere, with connecting vines freely weaving through the gaps between bricks.</p>
</div>
<h2 id="chapter-contents">Chapter contents<a class="headerlink" href="#chapter-contents" title="Permanent link">&para;</a></h2>
<ul>
<li><a href="array/">4.1 &nbsp; Array</a></li>
<li><a href="linked_list/">4.2 &nbsp; Linked list</a></li>
<li><a href="linked_list/">4.2 &nbsp; Linked List</a></li>
<li><a href="list/">4.3 &nbsp; List</a></li>
<li><a href="ram_and_cache/">4.4 &nbsp; Memory and cache *</a></li>
<li><a href="ram_and_cache/">4.4 &nbsp; Memory and Cache *</a></li>
<li><a href="summary/">4.5 &nbsp; Summary</a></li>
</ul>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -37,7 +37,7 @@
<title>4.4 Memory and cache * - Hello Algo</title>
<title>4.4 Memory and Cache * - Hello Algo</title>
@@ -58,8 +58,8 @@
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Lato:300,300i,400,400i,700,700i%7CJetBrains+Mono:400,400i,700,700i&display=fallback">
<style>:root{--md-text-font:"Lato";--md-code-font:"JetBrains Mono"}</style>
@@ -99,7 +99,7 @@
<div data-md-component="skip">
<a href="#44-memory-and-cache" class="md-skip">
<a href="#44-random-access-memory-and-cache" class="md-skip">
Skip to content
</a>
@@ -154,7 +154,7 @@
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
4.4 Memory and cache *
4.4 Memory and Cache *
</span>
</div>
@@ -371,7 +371,7 @@
<span class="md-ellipsis">
Before starting
Before Starting
@@ -388,7 +388,7 @@
<span class="md-nav__icon md-icon"></span>
Before starting
Before Starting
</label>
@@ -487,7 +487,7 @@
<span class="md-ellipsis">
0.1 About this book
0.1 About This Book
@@ -515,7 +515,7 @@
<span class="md-ellipsis">
0.2 How to read
0.2 How to Use This Book
@@ -604,7 +604,7 @@
<span class="md-ellipsis">
Chapter 1. Encounter with algorithms
Chapter 1. Encounter With Algorithms
@@ -626,7 +626,7 @@
<span class="md-nav__icon md-icon"></span>
Chapter 1. Encounter with algorithms
Chapter 1. Encounter With Algorithms
</label>
@@ -648,7 +648,7 @@
<span class="md-ellipsis">
1.1 Algorithms are everywhere
1.1 Algorithms Are Everywhere
@@ -676,7 +676,7 @@
<span class="md-ellipsis">
1.2 What is an algorithm
1.2 What Is an Algorithm
@@ -769,7 +769,7 @@
<span class="md-ellipsis">
Chapter 2. Complexity analysis
Chapter 2. Complexity Analysis
@@ -791,7 +791,7 @@
<span class="md-nav__icon md-icon"></span>
Chapter 2. Complexity analysis
Chapter 2. Complexity Analysis
</label>
@@ -813,7 +813,7 @@
<span class="md-ellipsis">
2.1 Algorithm efficiency assessment
2.1 Algorithm Efficiency Evaluation
@@ -841,7 +841,7 @@
<span class="md-ellipsis">
2.2 Iteration and recursion
2.2 Iteration and Recursion
@@ -869,7 +869,7 @@
<span class="md-ellipsis">
2.3 Time complexity
2.3 Time Complexity
@@ -897,7 +897,7 @@
<span class="md-ellipsis">
2.4 Space complexity
2.4 Space Complexity
@@ -990,7 +990,7 @@
<span class="md-ellipsis">
Chapter 3. Data structures
Chapter 3. Data Structures
@@ -1012,7 +1012,7 @@
<span class="md-nav__icon md-icon"></span>
Chapter 3. Data structures
Chapter 3. Data Structures
</label>
@@ -1034,7 +1034,7 @@
<span class="md-ellipsis">
3.1 Classification of data structures
3.1 Classification of Data Structures
@@ -1062,7 +1062,7 @@
<span class="md-ellipsis">
3.2 Basic data types
3.2 Basic Data Types
@@ -1090,7 +1090,7 @@
<span class="md-ellipsis">
3.3 Number encoding *
3.3 Number Encoding *
@@ -1118,7 +1118,7 @@
<span class="md-ellipsis">
3.4 Character encoding *
3.4 Character Encoding *
@@ -1213,7 +1213,7 @@
<span class="md-ellipsis">
Chapter 4. Array and linked list
Chapter 4. Array and Linked List
@@ -1235,7 +1235,7 @@
<span class="md-nav__icon md-icon"></span>
Chapter 4. Array and linked list
Chapter 4. Array and Linked List
</label>
@@ -1285,7 +1285,7 @@
<span class="md-ellipsis">
4.2 Linked list
4.2 Linked List
@@ -1350,7 +1350,7 @@
<span class="md-ellipsis">
4.4 Memory and cache *
4.4 Memory and Cache *
@@ -1368,7 +1368,7 @@
<span class="md-ellipsis">
4.4 Memory and cache *
4.4 Memory and Cache *
@@ -1397,7 +1397,7 @@
<a href="#441-computer-storage-devices" class="md-nav__link">
<span class="md-ellipsis">
4.4.1 &nbsp; Computer storage devices
4.4.1 &nbsp; Computer Storage Devices
</span>
</a>
@@ -1408,7 +1408,7 @@
<a href="#442-memory-efficiency-of-data-structures" class="md-nav__link">
<span class="md-ellipsis">
4.4.2 &nbsp; Memory efficiency of data structures
4.4.2 &nbsp; Memory Efficiency of Data Structures
</span>
</a>
@@ -1419,7 +1419,7 @@
<a href="#443-cache-efficiency-of-data-structures" class="md-nav__link">
<span class="md-ellipsis">
4.4.3 &nbsp; Cache efficiency of data structures
4.4.3 &nbsp; Cache Efficiency of Data Structures
</span>
</a>
@@ -1512,7 +1512,7 @@
<span class="md-ellipsis">
Chapter 5. Stack and queue
Chapter 5. Stack and Queue
@@ -1534,7 +1534,7 @@
<span class="md-nav__icon md-icon"></span>
Chapter 5. Stack and queue
Chapter 5. Stack and Queue
</label>
@@ -1612,7 +1612,7 @@
<span class="md-ellipsis">
5.3 Double-ended queue
5.3 Double-Ended Queue
@@ -1703,7 +1703,7 @@
<span class="md-ellipsis">
Chapter 6. Hash table
Chapter 6. Hashing
@@ -1725,7 +1725,7 @@
<span class="md-nav__icon md-icon"></span>
Chapter 6. Hash table
Chapter 6. Hashing
</label>
@@ -1747,7 +1747,7 @@
<span class="md-ellipsis">
6.1 Hash table
6.1 Hash Table
@@ -1775,7 +1775,7 @@
<span class="md-ellipsis">
6.2 Hash collision
6.2 Hash Collision
@@ -1803,7 +1803,7 @@
<span class="md-ellipsis">
6.3 Hash algorithm
6.3 Hash Algorithm
@@ -1942,7 +1942,7 @@
<span class="md-ellipsis">
7.1 Binary tree
7.1 Binary Tree
@@ -1970,7 +1970,7 @@
<span class="md-ellipsis">
7.2 Binary tree traversal
7.2 Binary Tree Traversal
@@ -1998,7 +1998,7 @@
<span class="md-ellipsis">
7.3 Array Representation of tree
7.3 Array Representation of Tree
@@ -2026,7 +2026,7 @@
<span class="md-ellipsis">
7.4 Binary Search tree
7.4 Binary Search Tree
@@ -2054,7 +2054,7 @@
<span class="md-ellipsis">
7.5 AVL tree *
7.5 AVL Tree *
@@ -2217,7 +2217,7 @@
<span class="md-ellipsis">
8.2 Building a heap
8.2 Building a Heap
@@ -2245,7 +2245,7 @@
<span class="md-ellipsis">
8.3 Top-k problem
8.3 Top-K Problem
@@ -2408,7 +2408,7 @@
<span class="md-ellipsis">
9.2 Basic graph operations
9.2 Basic Operations on Graphs
@@ -2436,7 +2436,7 @@
<span class="md-ellipsis">
9.3 Graph traversal
9.3 Graph Traversal
@@ -2575,7 +2575,7 @@
<span class="md-ellipsis">
10.1 Binary search
10.1 Binary Search
@@ -2603,7 +2603,7 @@
<span class="md-ellipsis">
10.2 Binary search insertion
10.2 Binary Search Insertion
@@ -2631,7 +2631,7 @@
<span class="md-ellipsis">
10.3 Binary search boundaries
10.3 Binary Search Edge Cases
@@ -2659,7 +2659,7 @@
<span class="md-ellipsis">
10.4 Hashing optimization strategies
10.4 Hash Optimization Strategy
@@ -2687,7 +2687,7 @@
<span class="md-ellipsis">
10.5 Search algorithms revisited
10.5 Search Algorithms Revisited
@@ -2836,7 +2836,7 @@
<span class="md-ellipsis">
11.1 Sorting algorithms
11.1 Sorting Algorithms
@@ -2864,7 +2864,7 @@
<span class="md-ellipsis">
11.2 Selection sort
11.2 Selection Sort
@@ -2892,7 +2892,7 @@
<span class="md-ellipsis">
11.3 Bubble sort
11.3 Bubble Sort
@@ -2920,7 +2920,7 @@
<span class="md-ellipsis">
11.4 Insertion sort
11.4 Insertion Sort
@@ -2948,7 +2948,7 @@
<span class="md-ellipsis">
11.5 Quick sort
11.5 Quick Sort
@@ -2976,7 +2976,7 @@
<span class="md-ellipsis">
11.6 Merge sort
11.6 Merge Sort
@@ -3004,7 +3004,7 @@
<span class="md-ellipsis">
11.7 Heap sort
11.7 Heap Sort
@@ -3032,7 +3032,7 @@
<span class="md-ellipsis">
11.8 Bucket sort
11.8 Bucket Sort
@@ -3060,7 +3060,7 @@
<span class="md-ellipsis">
11.9 Counting sort
11.9 Counting Sort
@@ -3088,7 +3088,7 @@
<span class="md-ellipsis">
11.10 Radix sort
11.10 Radix Sort
@@ -3181,7 +3181,7 @@
<span class="md-ellipsis">
Chapter 12. Divide and conquer
Chapter 12. Divide and Conquer
@@ -3203,7 +3203,7 @@
<span class="md-nav__icon md-icon"></span>
Chapter 12. Divide and conquer
Chapter 12. Divide and Conquer
</label>
@@ -3225,7 +3225,7 @@
<span class="md-ellipsis">
12.1 Divide and conquer algorithms
12.1 Divide and Conquer Algorithms
@@ -3253,7 +3253,7 @@
<span class="md-ellipsis">
12.2 Divide and conquer search strategy
12.2 Divide and Conquer Search Strategy
@@ -3281,7 +3281,7 @@
<span class="md-ellipsis">
12.3 Building binary tree problem
12.3 Building a Binary Tree Problem
@@ -3309,7 +3309,7 @@
<span class="md-ellipsis">
12.4 Tower of Hanoi Problem
12.4 Hanoi Tower Problem
@@ -3446,7 +3446,7 @@
<span class="md-ellipsis">
13.1 Backtracking algorithms
13.1 Backtracking Algorithm
@@ -3474,7 +3474,7 @@
<span class="md-ellipsis">
13.2 Permutation problem
13.2 Permutations Problem
@@ -3502,7 +3502,7 @@
<span class="md-ellipsis">
13.3 Subset sum problem
13.3 Subset-Sum Problem
@@ -3530,7 +3530,7 @@
<span class="md-ellipsis">
13.4 n queens problem
13.4 N-Queens Problem
@@ -3627,7 +3627,7 @@
<span class="md-ellipsis">
Chapter 14. Dynamic programming
Chapter 14. Dynamic Programming
@@ -3649,7 +3649,7 @@
<span class="md-nav__icon md-icon"></span>
Chapter 14. Dynamic programming
Chapter 14. Dynamic Programming
</label>
@@ -3671,7 +3671,7 @@
<span class="md-ellipsis">
14.1 Introduction to dynamic programming
14.1 Introduction to Dynamic Programming
@@ -3699,7 +3699,7 @@
<span class="md-ellipsis">
14.2 Characteristics of DP problems
14.2 Characteristics of Dynamic Programming Problems
@@ -3727,7 +3727,7 @@
<span class="md-ellipsis">
14.3 DP problem-solving approach
14.3 Dynamic Programming Problem-Solving Approach
@@ -3755,7 +3755,7 @@
<span class="md-ellipsis">
14.4 0-1 Knapsack problem
14.4 0-1 Knapsack Problem
@@ -3783,7 +3783,7 @@
<span class="md-ellipsis">
14.5 Unbounded knapsack problem
14.5 Unbounded Knapsack Problem
@@ -3811,7 +3811,7 @@
<span class="md-ellipsis">
14.6 Edit distance problem
14.6 Edit Distance Problem
@@ -3948,7 +3948,7 @@
<span class="md-ellipsis">
15.1 Greedy algorithms
15.1 Greedy Algorithm
@@ -3976,7 +3976,7 @@
<span class="md-ellipsis">
15.2 Fractional knapsack problem
15.2 Fractional Knapsack Problem
@@ -4004,7 +4004,7 @@
<span class="md-ellipsis">
15.3 Maximum capacity problem
15.3 Maximum Capacity Problem
@@ -4032,7 +4032,7 @@
<span class="md-ellipsis">
15.4 Maximum product cutting problem
15.4 Maximum Product Cutting Problem
@@ -4165,7 +4165,7 @@
<span class="md-ellipsis">
16.1 Installation
16.1 Programming Environment Installation
@@ -4193,7 +4193,7 @@
<span class="md-ellipsis">
16.2 Contributing
16.2 Contributing Together
@@ -4221,7 +4221,7 @@
<span class="md-ellipsis">
16.3 Terminology
16.3 Terminology Table
@@ -4338,7 +4338,7 @@
<a href="#441-computer-storage-devices" class="md-nav__link">
<span class="md-ellipsis">
4.4.1 &nbsp; Computer storage devices
4.4.1 &nbsp; Computer Storage Devices
</span>
</a>
@@ -4349,7 +4349,7 @@
<a href="#442-memory-efficiency-of-data-structures" class="md-nav__link">
<span class="md-ellipsis">
4.4.2 &nbsp; Memory efficiency of data structures
4.4.2 &nbsp; Memory Efficiency of Data Structures
</span>
</a>
@@ -4360,7 +4360,7 @@
<a href="#443-cache-efficiency-of-data-structures" class="md-nav__link">
<span class="md-ellipsis">
4.4.3 &nbsp; Cache efficiency of data structures
4.4.3 &nbsp; Cache Efficiency of Data Structures
</span>
</a>
@@ -4404,12 +4404,12 @@
<!-- Page content -->
<h1 id="44-memory-and-cache">4.4 &nbsp; Memory and cache *<a class="headerlink" href="#44-memory-and-cache" title="Permanent link">&para;</a></h1>
<p>In the first two sections of this chapter, we explored arrays and linked lists, two fundamental data structures that represent "continuous storage" and "dispersed storage," respectively.</p>
<p>In fact, <strong>the physical structure largely determines how efficiently a program utilizes memory and cache</strong>, which in turn affects the overall performance of the algorithm.</p>
<h2 id="441-computer-storage-devices">4.4.1 &nbsp; Computer storage devices<a class="headerlink" href="#441-computer-storage-devices" title="Permanent link">&para;</a></h2>
<p>There are three types of storage devices in computers: <u>hard disk</u>, <u>random-access memory (RAM)</u>, and <u>cache memory</u>. The following table shows their respective roles and performance characteristics in computer systems.</p>
<p align="center"> Table 4-2 &nbsp; Computer storage devices </p>
<h1 id="44-random-access-memory-and-cache">4.4 &nbsp; Random-Access Memory and Cache *<a class="headerlink" href="#44-random-access-memory-and-cache" title="Permanent link">&para;</a></h1>
<p>In the first two sections of this chapter, we explored arrays and linked lists, two fundamental and important data structures that represent "contiguous storage" and "distributed storage" as two physical structures, respectively.</p>
<p>In fact, <strong>physical structure largely determines the efficiency with which programs utilize memory and cache</strong>, which in turn affects the overall performance of algorithmic programs.</p>
<h2 id="441-computer-storage-devices">4.4.1 &nbsp; Computer Storage Devices<a class="headerlink" href="#441-computer-storage-devices" title="Permanent link">&para;</a></h2>
<p>Computers include three types of storage devices: <u>hard disk</u>, <u>random-access memory (RAM)</u>, and <u>cache memory</u>. The following table shows their different roles and performance characteristics in a computer system.</p>
<p align="center"> Table 4-2 &nbsp; Computer Storage Devices </p>
<div class="center-table">
<table>
@@ -4417,87 +4417,87 @@
<tr>
<th></th>
<th>Hard Disk</th>
<th>Memory</th>
<th>RAM</th>
<th>Cache</th>
</tr>
</thead>
<tbody>
<tr>
<td>Usage</td>
<td>Long-term storage of data, including OS, programs, files, etc.</td>
<td>Purpose</td>
<td>Long-term storage of data, including operating systems, programs, and files</td>
<td>Temporary storage of currently running programs and data being processed</td>
<td>Stores frequently accessed data and instructions, reducing the number of CPU accesses to memory</td>
<td>Storage of frequently accessed data and instructions to reduce CPU's accesses to memory</td>
</tr>
<tr>
<td>Volatility</td>
<td>Data is not lost after power off</td>
<td>Data is lost after power off</td>
<td>Data is lost after power off</td>
<td>Data is not lost after power-off</td>
<td>Data is lost after power-off</td>
<td>Data is lost after power-off</td>
</tr>
<tr>
<td>Capacity</td>
<td>Larger, TB level</td>
<td>Smaller, GB level</td>
<td>Very small, MB level</td>
<td>Large, on the order of terabytes (TB)</td>
<td>Small, on the order of gigabytes (GB)</td>
<td>Very small, on the order of megabytes (MB)</td>
</tr>
<tr>
<td>Speed</td>
<td>Slower, several hundred to thousands MB/s</td>
<td>Faster, several tens of GB/s</td>
<td>Very fast, several tens to hundreds of GB/s</td>
<td>Slow, hundreds to thousands of MB/s</td>
<td>Fast, tens of GB/s</td>
<td>Very fast, tens to hundreds of GB/s</td>
</tr>
<tr>
<td>Price (USD)</td>
<td>Cheaper, a few cents / GB</td>
<td>More expensive, a few dollars / GB</td>
<td>Very expensive, priced with CPU</td>
<td>Cost (USD/GB)</td>
<td>Inexpensive, fractions of a dollar to a few dollars per GB</td>
<td>Expensive, tens to hundreds of dollars per GB</td>
<td>Very expensive, priced as part of the CPU package</td>
</tr>
</tbody>
</table>
</div>
<p>The computer storage system can be visualized as a pyramid, as shown in Figure 4-9. The storage devices at the top of the pyramid are faster, have smaller capacities, and are more expensive. This multi-level design is not accidental, but a deliberate outcome of careful consideration by computer scientists and engineers.</p>
<p>We can imagine the computer storage system as a pyramid structure as shown in the diagram below. Storage devices closer to the top of the pyramid are faster, have smaller capacity, and are more expensive. This multi-layered design is not by accident, but rather the result of careful consideration by computer scientists and engineers.</p>
<ul>
<li><strong>Replacing hard disks with memory is challenging</strong>. Firstly, data in memory is lost after power off, making it unsuitable for long-term data storage; secondly, memory is significantly more expensive than hard disks, limiting its feasibility for widespread use in the consumer market.</li>
<li><strong>Caches face a trade-off between large capacity and high speed</strong>. As the capacity of L1, L2, and L3 caches increases, their physical size grows, increasing the distance from the CPU core. This results in longer data transfer times and higher access latency. With current technology, a multi-level cache structure provides the optimal balance between capacity, speed, and cost.</li>
<li><strong>Hard disk cannot be easily replaced by RAM</strong>. First, data in memory is lost after power-off, making it unsuitable for long-term data storage. Second, memory is tens of times more expensive than hard disk, which makes it difficult to popularize in the consumer market.</li>
<li><strong>Cache cannot simultaneously achieve large capacity and high speed</strong>. As the capacity of L1, L2, and L3 caches increases, their physical size becomes larger, and the physical distance between them and the CPU core increases, resulting in longer data transmission time and higher element access latency. With current technology, the multi-layered cache structure represents the best balance point between capacity, speed, and cost.</li>
</ul>
<p><a class="glightbox" href="../ram_and_cache.assets/storage_pyramid.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="Computer storage system" class="animation-figure" src="../ram_and_cache.assets/storage_pyramid.png" /></a></p>
<p align="center"> Figure 4-9 &nbsp; Computer storage system </p>
<p><a class="glightbox" href="../ram_and_cache.assets/storage_pyramid.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="Computer Storage System" class="animation-figure" src="../ram_and_cache.assets/storage_pyramid.png" /></a></p>
<p align="center"> Figure 4-9 &nbsp; Computer Storage System </p>
<div class="admonition tip">
<p class="admonition-title">Tip</p>
<p>The storage hierarchy in computers reflects a careful balance between speed, capacity, and cost. This type of trade-off is common across various industries, where finding the optimal balance between benefits and limitations is essential.</p>
<p>The storage hierarchy of computers embodies a delicate balance among speed, capacity, and cost. In fact, such trade-offs are common across all industrial fields, requiring us to find the optimal balance point between different advantages and constraints.</p>
</div>
<p>Overall, <strong>hard disks provide long-term storage for large volumes of data, memory serves as temporary storage for data being processed during program execution, and cache stores frequently accessed data and instructions to enhance execution efficiency</strong>. Together, they ensure the efficient operation of computer systems.</p>
<p>As shown in Figure 4-10, during program execution, data is read from the hard disk into memory for CPU computation. The cache, acting as an extension of the CPU, <strong>intelligently preloads data from memory</strong>, enabling faster data access for the CPU. This greatly improves program execution efficiency while reducing reliance on slower memory.</p>
<p><a class="glightbox" href="../ram_and_cache.assets/computer_storage_devices.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="Data flow between hard disk, memory, and cache" class="animation-figure" src="../ram_and_cache.assets/computer_storage_devices.png" /></a></p>
<p align="center"> Figure 4-10 &nbsp; Data flow between hard disk, memory, and cache </p>
<p>In summary, <strong>hard disk is used for long-term storage of large amounts of data, RAM is used for temporary storage of data being processed during program execution, and cache is used for storage of frequently accessed data and instructions</strong>, to improve program execution efficiency. The three work together to ensure efficient operation of the computer system.</p>
<p>As shown in the diagram below, during program execution, data is read from the hard disk into RAM for CPU computation. Cache can be viewed as part of the CPU, <strong>it intelligently loads data from RAM</strong>, providing the CPU with high-speed data reading, thereby significantly improving program execution efficiency and reducing reliance on slower RAM.</p>
<p><a class="glightbox" href="../ram_and_cache.assets/computer_storage_devices.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="Data Flow Among Hard Disk, RAM, and Cache" class="animation-figure" src="../ram_and_cache.assets/computer_storage_devices.png" /></a></p>
<p align="center"> Figure 4-10 &nbsp; Data Flow Among Hard Disk, RAM, and Cache </p>
<h2 id="442-memory-efficiency-of-data-structures">4.4.2 &nbsp; Memory efficiency of data structures<a class="headerlink" href="#442-memory-efficiency-of-data-structures" title="Permanent link">&para;</a></h2>
<p>In terms of memory space utilization, arrays and linked lists have their advantages and limitations.</p>
<p>On one hand, <strong>memory is limited and cannot be shared by multiple programs</strong>, so optimizing space usage in data structures is crucial. Arrays are space-efficient because their elements are tightly packed, without requiring extra memory for references (pointers) as in linked lists. However, arrays require pre-allocating a contiguous block of memory, which can lead to waste if the allocated space exceeds the actual need. Expanding an array also incurs additional time and space overhead. In contrast, linked lists allocate and free memory dynamically for each node, offering greater flexibility at the cost of additional memory for pointers.</p>
<p>On the other hand, during program execution, <strong>repeated memory allocation and deallocation increase memory fragmentation</strong>, reducing memory utilization efficiency. Arrays, due to their continuous storage method, are relatively less likely to cause memory fragmentation. In contrast, linked lists store elements in non-contiguous locations, and frequent insertions and deletions can exacerbate memory fragmentation.</p>
<h2 id="443-cache-efficiency-of-data-structures">4.4.3 &nbsp; Cache efficiency of data structures<a class="headerlink" href="#443-cache-efficiency-of-data-structures" title="Permanent link">&para;</a></h2>
<p>Although caches are much smaller in space capacity than memory, they are much faster and play a crucial role in program execution speed. Due to their limited capacity, caches can only store a subset of frequently accessed data. When the CPU attempts to access data not present in the cache, a <u>cache miss</u> occurs, requiring the CPU to retrieve the needed data from slower memory, which can impact performance.</p>
<p>Clearly, <strong>the fewer the cache misses, the higher the CPU's data read-write efficiency</strong>, and the better the program performance. The proportion of successful data retrieval from the cache by the CPU is called the <u>cache hit rate</u>, a metric often used to measure cache efficiency.</p>
<p>To achieve higher efficiency, caches adopt the following data loading mechanisms.</p>
<h2 id="442-memory-efficiency-of-data-structures">4.4.2 &nbsp; Memory Efficiency of Data Structures<a class="headerlink" href="#442-memory-efficiency-of-data-structures" title="Permanent link">&para;</a></h2>
<p>In terms of memory space utilization, arrays and linked lists each have advantages and limitations.</p>
<p>On one hand, <strong>memory is limited, and the same memory cannot be shared by multiple programs</strong>, so we hope data structures can utilize space as efficiently as possible. Array elements are tightly packed and do not require additional space to store references (pointers) between linked list nodes, thus having higher space efficiency. However, arrays need to allocate sufficient contiguous memory space at once, which may lead to memory waste, and array expansion requires additional time and space costs. In comparison, linked lists perform dynamic memory allocation and deallocation on a "node" basis, providing greater flexibility.</p>
<p>On the other hand, during program execution, <strong>as memory is repeatedly allocated and freed, the degree of fragmentation of free memory becomes increasingly severe</strong>, leading to reduced memory utilization efficiency. Arrays, due to their contiguous storage approach, are relatively less prone to memory fragmentation. Conversely, linked list elements are distributed in storage, and frequent insertion and deletion operations are more likely to cause memory fragmentation.</p>
<h2 id="443-cache-efficiency-of-data-structures">4.4.3 &nbsp; Cache Efficiency of Data Structures<a class="headerlink" href="#443-cache-efficiency-of-data-structures" title="Permanent link">&para;</a></h2>
<p>Although cache has much smaller space capacity than memory, it is much faster than memory and plays a crucial role in program execution speed. Since cache capacity is limited and can only store a small portion of frequently accessed data, when the CPU attempts to access data that is not in the cache, a <u>cache miss</u> occurs, and the CPU must load the required data from the slower memory.</p>
<p>Clearly, <strong>the fewer "cache misses," the higher the efficiency of CPU data reads and writes</strong>, and the better the program performance. We call the proportion of data that the CPU successfully obtains from the cache the <u>cache hit rate</u>, a metric typically used to measure cache efficiency.</p>
<p>To achieve the highest efficiency possible, cache employs the following data loading mechanisms.</p>
<ul>
<li><strong>Cache lines</strong>: Caches operate by storing and loading data in units called cache lines, rather than individual bytes. This approach improves efficiency by transferring larger blocks of data at once.</li>
<li><strong>Prefetch mechanism</strong>: Processors predict data access patterns (e.g., sequential or fixed-stride access) and preload data into the cache based on these patterns to increase the cache hit rate.</li>
<li><strong>Spatial locality</strong>: When a specific piece of data is accessed, nearby data is likely to be accessed soon. To leverage this, caches load adjacent data along with the requested data, improving hit rates.</li>
<li><strong>Temporal locality</strong>: If data is accessed, it's likely to be accessed again in the near future. Caches use this principle to retain recently accessed data to improve the hit rate.</li>
<li><strong>Cache lines</strong>: The cache does not store and load data on a byte-by-byte basis, but rather as cache lines. Compared to byte-by-byte transmission, cache line transmission is more efficient.</li>
<li><strong>Prefetching mechanism</strong>: The processor attempts to predict data access patterns (e.g., sequential access, fixed-stride jumping access, etc.) and loads data into the cache according to specific patterns, thereby improving hit rate.</li>
<li><strong>Spatial locality</strong>: If a piece of data is accessed, nearby data may also be accessed in the near future. Therefore, when the cache loads a particular piece of data, it also loads nearby data to improve hit rate.</li>
<li><strong>Temporal locality</strong>: If a piece of data is accessed, it is likely to be accessed again in the near future. Cache leverages this principle by retaining recently accessed data to improve hit rate.</li>
</ul>
<p>In fact, <strong>arrays and linked lists have different cache utilization efficiencies</strong>, which is mainly reflected in the following aspects.</p>
<p>In fact, <strong>arrays and linked lists have different efficiencies in utilizing cache</strong>, manifested in the following aspects.</p>
<ul>
<li><strong>Occupied space</strong>: Linked list elements take up more space than array elements, resulting in less effective data being held in the cache.</li>
<li><strong>Cache lines</strong>: Linked list data is scattered throughout the memory, and cache is "loaded by row", so the proportion of invalid data loaded is higher.</li>
<li><strong>Prefetch mechanism</strong>: The data access pattern of arrays is more "predictable" than that of linked lists, that is, it is easier for the system to guess the data that is about to be loaded.</li>
<li><strong>Spatial locality</strong>: Arrays are stored in a continuous memory space, so data near the data being loaded is more likely to be accessed soon.</li>
<li><strong>Space occupied</strong>: Linked list elements occupy more space than array elements, resulting in fewer effective data in the cache.</li>
<li><strong>Cache lines</strong>: Linked list data are scattered throughout memory, while cache loads "by lines," so the proportion of invalid data loaded is higher.</li>
<li><strong>Prefetching mechanism</strong>: Arrays have more "predictable" data access patterns than linked lists, making it easier for the system to guess which data will be loaded next.</li>
<li><strong>Spatial locality</strong>: Arrays are stored in centralized memory space, so data near loaded data is more likely to be accessed soon.</li>
</ul>
<p>Overall, <strong>arrays have a higher cache hit rate and are generally more efficient in operation than linked lists</strong>. This makes data structures based on arrays more popular in solving algorithmic problems.</p>
<p>It should be noted that <strong>high cache efficiency does not mean that arrays are always better than linked lists</strong>. The choice of data structure should depend on specific application requirements. For example, both arrays and linked lists can implement the "stack" data structure (which will be detailed in the next chapter), but they are suitable for different scenarios.</p>
<p>Overall, <strong>arrays have higher cache hit rates, thus they usually outperform linked lists in operation efficiency</strong>. This makes data structures implemented based on arrays more popular when solving algorithmic problems.</p>
<p>It is important to note that <strong>high cache efficiency does not mean arrays are superior to linked lists in all cases</strong>. In practical applications, which data structure to choose should be determined based on specific requirements. For example, both arrays and linked lists can implement the "stack" data structure (which will be discussed in detail in the next chapter), but they are suitable for different scenarios.</p>
<ul>
<li>In algorithm problems, we tend to choose stacks based on arrays because they provide higher operational efficiency and random access capabilities, with the only cost being the need to pre-allocate a certain amount of memory space for the array.</li>
<li>If the data volume is very large, highly dynamic, and the expected size of the stack is difficult to estimate, then a stack based on a linked list is a better choice. Linked lists can distribute a large amount of data in different parts of the memory and avoid the additional overhead of array expansion.</li>
<li>When solving algorithm problems, we tend to prefer stack implementations based on arrays, because they provide higher operation efficiency and the ability of random access, at the cost of needing to pre-allocate a certain amount of memory space for the array.</li>
<li>If the data volume is very large, the dynamic nature is high, and the expected size of the stack is difficult to estimate, then a stack implementation based on linked lists is more suitable. Linked lists can distribute large amounts of data across different parts of memory and avoid the additional overhead produced by array expansion.</li>
</ul>
<!-- Source file information -->

View File

@@ -58,8 +58,8 @@
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Lato:300,300i,400,400i,700,700i%7CJetBrains+Mono:400,400i,700,700i&display=fallback">
<style>:root{--md-text-font:"Lato";--md-code-font:"JetBrains Mono"}</style>
@@ -371,7 +371,7 @@
<span class="md-ellipsis">
Before starting
Before Starting
@@ -388,7 +388,7 @@
<span class="md-nav__icon md-icon"></span>
Before starting
Before Starting
</label>
@@ -487,7 +487,7 @@
<span class="md-ellipsis">
0.1 About this book
0.1 About This Book
@@ -515,7 +515,7 @@
<span class="md-ellipsis">
0.2 How to read
0.2 How to Use This Book
@@ -604,7 +604,7 @@
<span class="md-ellipsis">
Chapter 1. Encounter with algorithms
Chapter 1. Encounter With Algorithms
@@ -626,7 +626,7 @@
<span class="md-nav__icon md-icon"></span>
Chapter 1. Encounter with algorithms
Chapter 1. Encounter With Algorithms
</label>
@@ -648,7 +648,7 @@
<span class="md-ellipsis">
1.1 Algorithms are everywhere
1.1 Algorithms Are Everywhere
@@ -676,7 +676,7 @@
<span class="md-ellipsis">
1.2 What is an algorithm
1.2 What Is an Algorithm
@@ -769,7 +769,7 @@
<span class="md-ellipsis">
Chapter 2. Complexity analysis
Chapter 2. Complexity Analysis
@@ -791,7 +791,7 @@
<span class="md-nav__icon md-icon"></span>
Chapter 2. Complexity analysis
Chapter 2. Complexity Analysis
</label>
@@ -813,7 +813,7 @@
<span class="md-ellipsis">
2.1 Algorithm efficiency assessment
2.1 Algorithm Efficiency Evaluation
@@ -841,7 +841,7 @@
<span class="md-ellipsis">
2.2 Iteration and recursion
2.2 Iteration and Recursion
@@ -869,7 +869,7 @@
<span class="md-ellipsis">
2.3 Time complexity
2.3 Time Complexity
@@ -897,7 +897,7 @@
<span class="md-ellipsis">
2.4 Space complexity
2.4 Space Complexity
@@ -990,7 +990,7 @@
<span class="md-ellipsis">
Chapter 3. Data structures
Chapter 3. Data Structures
@@ -1012,7 +1012,7 @@
<span class="md-nav__icon md-icon"></span>
Chapter 3. Data structures
Chapter 3. Data Structures
</label>
@@ -1034,7 +1034,7 @@
<span class="md-ellipsis">
3.1 Classification of data structures
3.1 Classification of Data Structures
@@ -1062,7 +1062,7 @@
<span class="md-ellipsis">
3.2 Basic data types
3.2 Basic Data Types
@@ -1090,7 +1090,7 @@
<span class="md-ellipsis">
3.3 Number encoding *
3.3 Number Encoding *
@@ -1118,7 +1118,7 @@
<span class="md-ellipsis">
3.4 Character encoding *
3.4 Character Encoding *
@@ -1213,7 +1213,7 @@
<span class="md-ellipsis">
Chapter 4. Array and linked list
Chapter 4. Array and Linked List
@@ -1235,7 +1235,7 @@
<span class="md-nav__icon md-icon"></span>
Chapter 4. Array and linked list
Chapter 4. Array and Linked List
</label>
@@ -1285,7 +1285,7 @@
<span class="md-ellipsis">
4.2 Linked list
4.2 Linked List
@@ -1341,7 +1341,7 @@
<span class="md-ellipsis">
4.4 Memory and cache *
4.4 Memory and Cache *
@@ -1425,7 +1425,7 @@
<a href="#1-key-review" class="md-nav__link">
<span class="md-ellipsis">
1. &nbsp; Key review
1. &nbsp; Key Review
</span>
</a>
@@ -1501,7 +1501,7 @@
<span class="md-ellipsis">
Chapter 5. Stack and queue
Chapter 5. Stack and Queue
@@ -1523,7 +1523,7 @@
<span class="md-nav__icon md-icon"></span>
Chapter 5. Stack and queue
Chapter 5. Stack and Queue
</label>
@@ -1601,7 +1601,7 @@
<span class="md-ellipsis">
5.3 Double-ended queue
5.3 Double-Ended Queue
@@ -1692,7 +1692,7 @@
<span class="md-ellipsis">
Chapter 6. Hash table
Chapter 6. Hashing
@@ -1714,7 +1714,7 @@
<span class="md-nav__icon md-icon"></span>
Chapter 6. Hash table
Chapter 6. Hashing
</label>
@@ -1736,7 +1736,7 @@
<span class="md-ellipsis">
6.1 Hash table
6.1 Hash Table
@@ -1764,7 +1764,7 @@
<span class="md-ellipsis">
6.2 Hash collision
6.2 Hash Collision
@@ -1792,7 +1792,7 @@
<span class="md-ellipsis">
6.3 Hash algorithm
6.3 Hash Algorithm
@@ -1931,7 +1931,7 @@
<span class="md-ellipsis">
7.1 Binary tree
7.1 Binary Tree
@@ -1959,7 +1959,7 @@
<span class="md-ellipsis">
7.2 Binary tree traversal
7.2 Binary Tree Traversal
@@ -1987,7 +1987,7 @@
<span class="md-ellipsis">
7.3 Array Representation of tree
7.3 Array Representation of Tree
@@ -2015,7 +2015,7 @@
<span class="md-ellipsis">
7.4 Binary Search tree
7.4 Binary Search Tree
@@ -2043,7 +2043,7 @@
<span class="md-ellipsis">
7.5 AVL tree *
7.5 AVL Tree *
@@ -2206,7 +2206,7 @@
<span class="md-ellipsis">
8.2 Building a heap
8.2 Building a Heap
@@ -2234,7 +2234,7 @@
<span class="md-ellipsis">
8.3 Top-k problem
8.3 Top-K Problem
@@ -2397,7 +2397,7 @@
<span class="md-ellipsis">
9.2 Basic graph operations
9.2 Basic Operations on Graphs
@@ -2425,7 +2425,7 @@
<span class="md-ellipsis">
9.3 Graph traversal
9.3 Graph Traversal
@@ -2564,7 +2564,7 @@
<span class="md-ellipsis">
10.1 Binary search
10.1 Binary Search
@@ -2592,7 +2592,7 @@
<span class="md-ellipsis">
10.2 Binary search insertion
10.2 Binary Search Insertion
@@ -2620,7 +2620,7 @@
<span class="md-ellipsis">
10.3 Binary search boundaries
10.3 Binary Search Edge Cases
@@ -2648,7 +2648,7 @@
<span class="md-ellipsis">
10.4 Hashing optimization strategies
10.4 Hash Optimization Strategy
@@ -2676,7 +2676,7 @@
<span class="md-ellipsis">
10.5 Search algorithms revisited
10.5 Search Algorithms Revisited
@@ -2825,7 +2825,7 @@
<span class="md-ellipsis">
11.1 Sorting algorithms
11.1 Sorting Algorithms
@@ -2853,7 +2853,7 @@
<span class="md-ellipsis">
11.2 Selection sort
11.2 Selection Sort
@@ -2881,7 +2881,7 @@
<span class="md-ellipsis">
11.3 Bubble sort
11.3 Bubble Sort
@@ -2909,7 +2909,7 @@
<span class="md-ellipsis">
11.4 Insertion sort
11.4 Insertion Sort
@@ -2937,7 +2937,7 @@
<span class="md-ellipsis">
11.5 Quick sort
11.5 Quick Sort
@@ -2965,7 +2965,7 @@
<span class="md-ellipsis">
11.6 Merge sort
11.6 Merge Sort
@@ -2993,7 +2993,7 @@
<span class="md-ellipsis">
11.7 Heap sort
11.7 Heap Sort
@@ -3021,7 +3021,7 @@
<span class="md-ellipsis">
11.8 Bucket sort
11.8 Bucket Sort
@@ -3049,7 +3049,7 @@
<span class="md-ellipsis">
11.9 Counting sort
11.9 Counting Sort
@@ -3077,7 +3077,7 @@
<span class="md-ellipsis">
11.10 Radix sort
11.10 Radix Sort
@@ -3170,7 +3170,7 @@
<span class="md-ellipsis">
Chapter 12. Divide and conquer
Chapter 12. Divide and Conquer
@@ -3192,7 +3192,7 @@
<span class="md-nav__icon md-icon"></span>
Chapter 12. Divide and conquer
Chapter 12. Divide and Conquer
</label>
@@ -3214,7 +3214,7 @@
<span class="md-ellipsis">
12.1 Divide and conquer algorithms
12.1 Divide and Conquer Algorithms
@@ -3242,7 +3242,7 @@
<span class="md-ellipsis">
12.2 Divide and conquer search strategy
12.2 Divide and Conquer Search Strategy
@@ -3270,7 +3270,7 @@
<span class="md-ellipsis">
12.3 Building binary tree problem
12.3 Building a Binary Tree Problem
@@ -3298,7 +3298,7 @@
<span class="md-ellipsis">
12.4 Tower of Hanoi Problem
12.4 Hanoi Tower Problem
@@ -3435,7 +3435,7 @@
<span class="md-ellipsis">
13.1 Backtracking algorithms
13.1 Backtracking Algorithm
@@ -3463,7 +3463,7 @@
<span class="md-ellipsis">
13.2 Permutation problem
13.2 Permutations Problem
@@ -3491,7 +3491,7 @@
<span class="md-ellipsis">
13.3 Subset sum problem
13.3 Subset-Sum Problem
@@ -3519,7 +3519,7 @@
<span class="md-ellipsis">
13.4 n queens problem
13.4 N-Queens Problem
@@ -3616,7 +3616,7 @@
<span class="md-ellipsis">
Chapter 14. Dynamic programming
Chapter 14. Dynamic Programming
@@ -3638,7 +3638,7 @@
<span class="md-nav__icon md-icon"></span>
Chapter 14. Dynamic programming
Chapter 14. Dynamic Programming
</label>
@@ -3660,7 +3660,7 @@
<span class="md-ellipsis">
14.1 Introduction to dynamic programming
14.1 Introduction to Dynamic Programming
@@ -3688,7 +3688,7 @@
<span class="md-ellipsis">
14.2 Characteristics of DP problems
14.2 Characteristics of Dynamic Programming Problems
@@ -3716,7 +3716,7 @@
<span class="md-ellipsis">
14.3 DP problem-solving approach
14.3 Dynamic Programming Problem-Solving Approach
@@ -3744,7 +3744,7 @@
<span class="md-ellipsis">
14.4 0-1 Knapsack problem
14.4 0-1 Knapsack Problem
@@ -3772,7 +3772,7 @@
<span class="md-ellipsis">
14.5 Unbounded knapsack problem
14.5 Unbounded Knapsack Problem
@@ -3800,7 +3800,7 @@
<span class="md-ellipsis">
14.6 Edit distance problem
14.6 Edit Distance Problem
@@ -3937,7 +3937,7 @@
<span class="md-ellipsis">
15.1 Greedy algorithms
15.1 Greedy Algorithm
@@ -3965,7 +3965,7 @@
<span class="md-ellipsis">
15.2 Fractional knapsack problem
15.2 Fractional Knapsack Problem
@@ -3993,7 +3993,7 @@
<span class="md-ellipsis">
15.3 Maximum capacity problem
15.3 Maximum Capacity Problem
@@ -4021,7 +4021,7 @@
<span class="md-ellipsis">
15.4 Maximum product cutting problem
15.4 Maximum Product Cutting Problem
@@ -4154,7 +4154,7 @@
<span class="md-ellipsis">
16.1 Installation
16.1 Programming Environment Installation
@@ -4182,7 +4182,7 @@
<span class="md-ellipsis">
16.2 Contributing
16.2 Contributing Together
@@ -4210,7 +4210,7 @@
<span class="md-ellipsis">
16.3 Terminology
16.3 Terminology Table
@@ -4327,7 +4327,7 @@
<a href="#1-key-review" class="md-nav__link">
<span class="md-ellipsis">
1. &nbsp; Key review
1. &nbsp; Key Review
</span>
</a>
@@ -4383,60 +4383,62 @@
<!-- Page content -->
<h1 id="45-summary">4.5 &nbsp; Summary<a class="headerlink" href="#45-summary" title="Permanent link">&para;</a></h1>
<h3 id="1-key-review">1. &nbsp; Key review<a class="headerlink" href="#1-key-review" title="Permanent link">&para;</a></h3>
<h3 id="1-key-review">1. &nbsp; Key Review<a class="headerlink" href="#1-key-review" title="Permanent link">&para;</a></h3>
<ul>
<li>Arrays and linked lists are two basic data structures, representing two storage methods in computer memory: contiguous space storage and non-contiguous space storage. Their characteristics complement each other.</li>
<li>Arrays support random access and use less memory; however, they are inefficient in inserting and deleting elements and have a fixed length after initialization.</li>
<li>Linked lists implement efficient node insertion and deletion through changing references (pointers) and can flexibly adjust their length; however, they have lower node access efficiency and consume more memory.</li>
<li>Common types of linked lists include singly linked lists, circular linked lists, and doubly linked lists, each with its own application scenarios.</li>
<li>Lists are ordered collections of elements that support addition, deletion, and modification, typically implemented based on dynamic arrays, retaining the advantages of arrays while allowing flexible length adjustment.</li>
<li>The advent of lists significantly enhanced the practicality of arrays but may lead to some memory space wastage.</li>
<li>During program execution, data is mainly stored in memory. Arrays provide higher memory space efficiency, while linked lists are more flexible in memory usage.</li>
<li>Caches provide fast data access to CPUs through mechanisms like cache lines, prefetching, spatial locality, and temporal locality, significantly enhancing program execution efficiency.</li>
<li>Due to higher cache hit rates, arrays are generally more efficient than linked lists. When choosing a data structure, the appropriate choice should be made based on specific needs and scenarios.</li>
<li>Arrays and linked lists are two fundamental data structures, representing two different ways data can be stored in computer memory: contiguous memory storage and scattered memory storage. The characteristics of the two complement each other.</li>
<li>Arrays support random access and use less memory; however, inserting and deleting elements is inefficient, and the length is immutable after initialization.</li>
<li>Linked lists achieve efficient insertion and deletion of nodes by modifying references (pointers), and can flexibly adjust length; however, node access is inefficient and memory consumption is higher. Common linked list types include singly linked lists, circular linked lists, and doubly linked lists.</li>
<li>A list is an ordered collection of elements that supports insertion, deletion, search, and modification, typically implemented based on dynamic arrays. It retains the advantages of arrays while allowing flexible adjustment of length.</li>
<li>The emergence of lists has greatly improved the practicality of arrays, but may result in some wasted memory space.</li>
<li>During program execution, data is primarily stored in memory. Arrays provide higher memory space efficiency, while linked lists offer greater flexibility in memory usage.</li>
<li>Caches provide fast data access to the CPU through mechanisms such as cache lines, prefetching, and spatial and temporal locality, significantly improving program execution efficiency.</li>
<li>Because arrays have higher cache hit rates, they are generally more efficient than linked lists. When choosing a data structure, appropriate selection should be made based on specific requirements and scenarios.</li>
</ul>
<h3 id="2-q-a">2. &nbsp; Q &amp; A<a class="headerlink" href="#2-q-a" title="Permanent link">&para;</a></h3>
<p><strong>Q</strong>: Does storing arrays on the stack versus the heap affect time and space efficiency?</p>
<p>Arrays stored on both the stack and heap are stored in contiguous memory spaces, and data operation efficiency is essentially the same. However, stacks and heaps have their own characteristics, leading to the following differences.</p>
<p><strong>Q</strong>: Does storing an array on the stack versus on the heap affect time efficiency and space efficiency?</p>
<p>Arrays stored on the stack and on the heap are both stored in contiguous memory space, so data operation efficiency is basically the same. However, the stack and heap have their own characteristics, leading to the following differences.</p>
<ol>
<li>Allocation and release efficiency: The stack is a smaller memory block, allocated automatically by the compiler; the heap memory is relatively larger and can be dynamically allocated in the code, more prone to fragmentation. Therefore, allocation and release operations on the heap are generally slower than on the stack.</li>
<li>Size limitation: Stack memory is relatively small, while the heap size is generally limited by available memory. Therefore, the heap is more suitable for storing large arrays.</li>
<li>Flexibility: The size of arrays on the stack needs to be determined at compile-time, while the size of arrays on the heap can be dynamically determined at runtime.</li>
<li>Allocation and deallocation efficiency: The stack is a relatively small piece of memory, with allocation automatically handled by the compiler; the heap is relatively larger and can be dynamically allocated in code, more prone to fragmentation. Therefore, allocation and deallocation operations on the heap are usually slower than on the stack.</li>
<li>Size limitations: Stack memory is relatively small, and the heap size is generally limited by available memory. Therefore, the heap is more suitable for storing large arrays.</li>
<li>Flexibility: The size of an array on the stack must be determined at compile time, while the size of an array on the heap can be determined dynamically at runtime.</li>
</ol>
<p><strong>Q</strong>: Why do arrays require elements of the same type, while linked lists do not emphasize same-type elements?</p>
<p>Linked lists consist of nodes connected by references (pointers), and each node can store data of different types, such as int, double, string, object, etc.</p>
<p>In contrast, array elements must be of the same type, allowing the calculation of offsets to access the corresponding element positions. For example, an array containing both int and long types, with single elements occupying 4 bytes and 8 bytes respectively, cannot use the following formula to calculate offsets, as the array contains elements of two different lengths.</p>
<div class="highlight"><pre><span></span><code><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="c1"># Element memory address = array memory address + element length * element index</span>
<p><strong>Q</strong>: Why do arrays require elements of the same type, while linked lists do not emphasize this requirement?</p>
<p>Linked lists are composed of nodes, with nodes connected through references (pointers), and each node can store different types of data, such as <code>int</code>, <code>double</code>, <code>string</code>, <code>object</code>, etc.</p>
<p>In contrast, array elements must be of the same type, so that the corresponding element position can be obtained by calculating the offset. For example, if an array contains both <code>int</code> and <code>long</code> types, with individual elements occupying 4 bytes and 8 bytes respectively, then the following formula cannot be used to calculate the offset, because the array contains two different "element lengths".</p>
<div class="highlight"><pre><span></span><code><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="c1"># Element Memory Address = Array Memory Address (first Element Memory address) + Element Length * Element Index</span>
</code></pre></div>
<p><strong>Q</strong>: After deleting a node, is it necessary to set <code>P.next</code> to <code>None</code>?</p>
<p>Not modifying <code>P.next</code> is also acceptable. From the perspective of the linked list, traversing from the head node to the tail node will no longer encounter <code>P</code>. This means that node <code>P</code> has been effectively removed from the list, and where <code>P</code> points no longer affects the list.</p>
<p>From a garbage collection perspective, for languages with automatic garbage collection mechanisms like Java, Python, and Go, whether node <code>P</code> is collected depends on whether there are still references pointing to it, not on the value of <code>P.next</code>. In languages like C and C++, we need to manually free the node's memory.</p>
<p><strong>Q</strong>: In linked lists, the time complexity for insertion and deletion operations is <code>O(1)</code>. But searching for the element before insertion or deletion takes <code>O(n)</code> time, so why isn't the time complexity <code>O(n)</code>?</p>
<p>If an element is searched first and then deleted, the time complexity is indeed <code>O(n)</code>. However, the <code>O(1)</code> advantage of linked lists in insertion and deletion can be realized in other applications. For example, in the implementation of double-ended queues using linked lists, we maintain pointers always pointing to the head and tail nodes, making each insertion and deletion operation <code>O(1)</code>.</p>
<p><strong>Q</strong>: In the figure "Linked List Definition and Storage Method", do the light blue storage nodes occupy a single memory address, or do they share half with the node value?</p>
<p>The figure is just a qualitative representation; quantitative analysis depends on specific situations.</p>
<p><strong>Q</strong>: After deleting node <code>P</code>, do we need to set <code>P.next</code> to <code>None</code>?</p>
<p>It is not necessary to modify <code>P.next</code>. From the perspective of the linked list, traversing from the head node to the tail node will no longer encounter <code>P</code>. This means that node <code>P</code> has been removed from the linked list, and it doesn't matter where node <code>P</code> points to at this time—it won't affect the linked list.</p>
<p>From a data structures and algorithms perspective (problem-solving), not disconnecting the pointer doesn't matter as long as the program logic is correct. From the perspective of standard libraries, disconnecting is safer and the logic is clearer. If not disconnected, assuming the deleted node is not properly reclaimed, it may affect the memory reclamation of its successor nodes.</p>
<p><strong>Q</strong>: In a linked list, the time complexity of insertion and deletion operations is <span class="arithmatex">\(O(1)\)</span>. However, both insertion and deletion require <span class="arithmatex">\(O(n)\)</span> time to find the element; why isn't the time complexity <span class="arithmatex">\(O(n)\)</span>?</p>
<p>If the element is first found and then deleted, the time complexity is indeed <span class="arithmatex">\(O(n)\)</span>. However, the advantage of <span class="arithmatex">\(O(1)\)</span> insertion and deletion in linked lists can be demonstrated in other applications. For example, a deque is well-suited for linked list implementation, where we maintain pointer variables always pointing to the head and tail nodes, with each insertion and deletion operation being <span class="arithmatex">\(O(1)\)</span>.</p>
<p><strong>Q</strong>: In the diagram "Linked List Definition and Storage Methods", does the light blue pointer node occupy a single memory address, or does it share equally with the node value?</p>
<p>This diagram is a qualitative representation; a quantitative representation requires analysis based on the specific situation.</p>
<ul>
<li>Different types of node values occupy different amounts of space, such as int, long, double, and object instances.</li>
<li>The memory space occupied by pointer variables depends on the operating system and compilation environment used, usually 8 bytes or 4 bytes.</li>
<li>Different types of node values occupy different amounts of space, such as <code>int</code>, <code>long</code>, <code>double</code>, and instance objects, etc.</li>
<li>The amount of memory space occupied by pointer variables depends on the operating system and compilation environment used, usually 8 bytes or 4 bytes.</li>
</ul>
<p><strong>Q</strong>: Is adding elements to the end of a list always <code>O(1)</code>?</p>
<p>If adding an element exceeds the list length, the list needs to be expanded first. The system will request a new memory block and move all elements of the original list over, in which case the time complexity becomes <code>O(n)</code>.</p>
<p><strong>Q</strong>: The statement "The emergence of lists greatly improves the practicality of arrays, but may lead to some memory space wastage" - does this refer to the memory occupied by additional variables like capacity, length, and expansion multiplier?</p>
<p>The space wastage here mainly refers to two aspects: on the one hand, lists are set with an initial length, which we may not always need; on the other hand, to prevent frequent expansion, expansion usually multiplies by a coefficient, such as <span class="arithmatex">\(\times 1.5\)</span>. This results in many empty slots, which we typically cannot fully fill.</p>
<p><strong>Q</strong>: In Python, after initializing <code>n = [1, 2, 3]</code>, the addresses of these 3 elements are contiguous, but initializing <code>m = [2, 1, 3]</code> shows that each element's <code>id</code> is not consecutive but identical to those in <code>n</code>. If the addresses of these elements are not contiguous, is <code>m</code> still an array?</p>
<p>If we replace list elements with linked list nodes <code>n = [n1, n2, n3, n4, n5]</code>, these 5 node objects are also typically dispersed throughout memory. However, given a list index, we can still access the node's memory address in <code>O(1)</code> time, thereby accessing the corresponding node. This is because the array stores references to the nodes, not the nodes themselves.</p>
<p>Unlike many languages, in Python, numbers are also wrapped as objects, and lists store references to these numbers, not the numbers themselves. Therefore, we find that the same number in two arrays has the same <code>id</code>, and these numbers' memory addresses need not be contiguous.</p>
<p><strong>Q</strong>: The <code>std::list</code> in C++ STL has already implemented a doubly linked list, but it seems that some algorithm books don't directly use it. Is there any limitation?</p>
<p>On the one hand, we often prefer to use arrays to implement algorithms, only using linked lists when necessary, mainly for two reasons.</p>
<p><strong>Q</strong>: Is appending an element at the end of a list always <span class="arithmatex">\(O(1)\)</span>?</p>
<p>If appending an element exceeds the list length, the list must first be expanded before adding. The system allocates a new block of memory and moves all elements from the original list to it, in which case the time complexity becomes <span class="arithmatex">\(O(n)\)</span>.</p>
<p><strong>Q</strong>: "The emergence of lists has greatly improved the practicality of arrays, but may result in some wasted memory space"—does this space waste refer to the memory occupied by additional variables such as capacity, length, and expansion factor?</p>
<p>This space waste mainly has two aspects: on one hand, lists typically set an initial length, which we may not need to fully utilize; on the other hand, to prevent frequent expansion, expansion generally multiplies by a coefficient, such as <span class="arithmatex">\(\times 1.5\)</span>. As a result, there will be many empty positions that we typically cannot completely fill.</p>
<p><strong>Q</strong>: In Python, after initializing <code>n = [1, 2, 3]</code>, the addresses of these 3 elements are contiguous, but initializing <code>m = [2, 1, 3]</code> reveals that each element's id is not continuous; rather, they are the same as those in <code>n</code>. Since the addresses of these elements are not contiguous, is <code>m</code> still an array?</p>
<p>If we replace list elements with linked list nodes <code>n = [n1, n2, n3, n4, n5]</code>, usually these 5 node objects are also scattered throughout memory. However, given a list index, we can still obtain the node memory address in <span class="arithmatex">\(O(1)\)</span> time, thereby accessing the corresponding node. This is because the array stores references to nodes, not the nodes themselves.</p>
<p>Unlike many languages, numbers in Python are wrapped as objects, and lists store not the numbers themselves, but references to the numbers. Therefore, we find that the same numbers in two arrays have the same id, and the memory addresses of these numbers need not be contiguous.</p>
<p><strong>Q</strong>: C++ STL has <code>std::list</code> which has already implemented a doubly linked list, but it seems that some algorithm books don't use it directly. Is there a limitation?</p>
<p>On one hand, we often prefer to use arrays for implementing algorithms and only use linked lists when necessary, mainly for two reasons.</p>
<ul>
<li>Space overhead: Since each element requires two additional pointers (one for the previous element and one for the next), <code>std::list</code> usually occupies more space than <code>std::vector</code>.</li>
<li>Cache unfriendly: As the data is not stored continuously, <code>std::list</code> has a lower cache utilization rate. Generally, <code>std::vector</code> performs better.</li>
<li>Space overhead: Since each element requires two additional pointers (one for the previous element and one for the next element), <code>std::list</code> typically consumes more space than <code>std::vector</code>.</li>
<li>Cache unfriendliness: Since data is not stored contiguously, <code>std::list</code> has lower cache utilization. In general, <code>std::vector</code> has better performance.</li>
</ul>
<p>On the other hand, linked lists are primarily necessary for binary trees and graphs. Stacks and queues are often implemented using the programming language's <code>stack</code> and <code>queue</code> classes, rather than linked lists.</p>
<p><strong>Q</strong>: Does initializing a list <code>res = [0] * self.size()</code> result in each element of <code>res</code> referencing the same address?</p>
<p>No. However, this issue arises with two-dimensional arrays, for example, initializing a two-dimensional list <code>res = [[0]] * self.size()</code> would reference the same list <code>[0]</code> multiple times.</p>
<p><strong>Q</strong>: In deleting a node, is it necessary to break the reference to its successor node?</p>
<p>From the perspective of data structures and algorithms (problem-solving), it's okay not to break the link, as long as the program's logic is correct. From the perspective of standard libraries, breaking the link is safer and more logically clear. If the link is not broken, and the deleted node is not properly recycled, it could affect the recycling of the successor node's memory.</p>
<p>On the other hand, cases where linked lists are necessary mainly involve binary trees and graphs. Stacks and queues usually use the <code>stack</code> and <code>queue</code> provided by the programming language, rather than linked lists.</p>
<p><strong>Q</strong>: Does the operation <code>res = [[0]] * n</code> create a 2D list where each <code>[0]</code> is independent?</p>
<p>No, they are not independent. In this 2D list, all the <code>[0]</code> are actually references to the same object. If we modify one element, we will find that all corresponding elements change accordingly.</p>
<p>If we want each <code>[0]</code> in the 2D list to be independent, we can use <code>res = [[0] for _ in range(n)]</code> to achieve this. The principle of this approach is to initialize <span class="arithmatex">\(n\)</span> independent <code>[0]</code> list objects.</p>
<p><strong>Q</strong>: Does the operation <code>res = [0] * n</code> create a list where each integer 0 is independent?</p>
<p>In this list, all integer 0s are references to the same object. This is because Python uses a caching mechanism for small integers (typically -5 to 256) to maximize object reuse and improve performance.</p>
<p>Although they point to the same object, we can still independently modify each element in the list. This is because Python integers are "immutable objects". When we modify an element, we are actually switching to a reference of another object, rather than changing the original object itself.</p>
<p>However, when list elements are "mutable objects" (such as lists, dictionaries, or class instances), modifying an element directly changes the object itself, and all elements referencing that object will have the same change.</p>
<!-- Source file information -->
@@ -4459,7 +4461,7 @@ aria-label="Footer"
<a
href="../ram_and_cache/"
class="md-footer__link md-footer__link--prev"
aria-label="Previous: 4.4 Memory and cache *"
aria-label="Previous: 4.4 Memory and Cache *"
rel="prev"
>
<div class="md-footer__button md-icon">
@@ -4471,7 +4473,7 @@ aria-label="Footer"
Previous
</span>
<div class="md-ellipsis">
4.4 Memory and cache *
4.4 Memory and Cache *
</div>
</div>
</a>
@@ -4483,7 +4485,7 @@ aria-label="Footer"
<a
href="../../chapter_stack_and_queue/"
class="md-footer__link md-footer__link--next"
aria-label="Next: Chapter 5. &amp;nbsp; Stack and queue"
aria-label="Next: Chapter 5. &amp;nbsp; Stack and Queue"
rel="next"
>
<div class="md-footer__title">
@@ -4491,7 +4493,7 @@ aria-label="Footer"
Next
</span>
<div class="md-ellipsis">
Chapter 5. &nbsp; Stack and queue
Chapter 5. &nbsp; Stack and Queue
</div>
</div>
<div class="md-footer__button md-icon">
@@ -4584,7 +4586,7 @@ aria-label="Footer"
<nav class="md-footer__inner md-grid" aria-label="Footer" >
<a href="../ram_and_cache/" class="md-footer__link md-footer__link--prev" aria-label="Previous: 4.4 Memory and cache *">
<a href="../ram_and_cache/" class="md-footer__link md-footer__link--prev" aria-label="Previous: 4.4 Memory and Cache *">
<div class="md-footer__button md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg>
@@ -4594,20 +4596,20 @@ aria-label="Footer"
Previous
</span>
<div class="md-ellipsis">
4.4 Memory and cache *
4.4 Memory and Cache *
</div>
</div>
</a>
<a href="../../chapter_stack_and_queue/" class="md-footer__link md-footer__link--next" aria-label="Next: Chapter 5. &amp;nbsp; Stack and queue">
<a href="../../chapter_stack_and_queue/" class="md-footer__link md-footer__link--next" aria-label="Next: Chapter 5. &amp;nbsp; Stack and Queue">
<div class="md-footer__title">
<span class="md-footer__direction">
Next
</span>
<div class="md-ellipsis">
Chapter 5. &nbsp; Stack and queue
Chapter 5. &nbsp; Stack and Queue
</div>
</div>
<div class="md-footer__button md-icon">