This commit is contained in:
krahets
2024-04-06 03:02:26 +08:00
parent 5988d20958
commit a263b839b9
875 changed files with 484736 additions and 2893 deletions

View File

@@ -26,7 +26,7 @@
<title>5.3 Double-ended Queue - Hello Algo</title>
<title>5.3 Double-ended queue - Hello Algo</title>
@@ -153,7 +153,7 @@
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
5.3 Double-ended Queue
5.3 Double-ended queue
</span>
</div>
@@ -201,7 +201,13 @@
<li class="md-select__item">
<a href="/" hreflang="zh" class="md-select__link">
中文
简体中文
</a>
</li>
<li class="md-select__item">
<a href="/zh-hant/" hreflang="zh-Hant" class="md-select__link">
繁體中文
</a>
</li>
@@ -393,7 +399,7 @@
<span class="md-ellipsis">
0.1 About This Book
0.1 About this book
</span>
@@ -414,7 +420,7 @@
<span class="md-ellipsis">
0.2 How to Read
0.2 How to read
</span>
@@ -491,7 +497,7 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2m0 16H5V5h14v14M6.2 7.7h5v1.5h-5V7.7m6.8 8.1h5v1.5h-5v-1.5m0-2.6h5v1.5h-5v-1.5M8 18h1.5v-2h2v-1.5h-2v-2H8v2H6V16h2v2m6.1-7.1 1.4-1.4 1.4 1.4 1.1-1-1.4-1.4L18 7.1 16.9 6l-1.4 1.4L14.1 6 13 7.1l1.4 1.4L13 9.9l1.1 1Z"/></svg>
<span class="md-ellipsis">
Chapter 1. Introduction to Algorithms
Chapter 1. Introduction to algorithms
</span>
@@ -507,7 +513,7 @@
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_2_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_2">
<span class="md-nav__icon md-icon"></span>
Chapter 1. Introduction to Algorithms
Chapter 1. Introduction to algorithms
</label>
<ul class="md-nav__list" data-md-scrollfix>
@@ -524,7 +530,7 @@
<span class="md-ellipsis">
1.1 Algorithms are Everywhere
1.1 Algorithms are everywhere
</span>
@@ -545,7 +551,7 @@
<span class="md-ellipsis">
1.2 What is an Algorithm
1.2 What is an algorithm
</span>
@@ -626,7 +632,7 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M6 2h12v6l-4 4 4 4v6H6v-6l4-4-4-4V2m10 14.5-4-4-4 4V20h8v-3.5m-4-5 4-4V4H8v3.5l4 4M10 6h4v.75l-2 2-2-2V6Z"/></svg>
<span class="md-ellipsis">
Chapter 2. Complexity Analysis
Chapter 2. Complexity analysis
</span>
@@ -642,7 +648,7 @@
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_3_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3">
<span class="md-nav__icon md-icon"></span>
Chapter 2. Complexity Analysis
Chapter 2. Complexity analysis
</label>
<ul class="md-nav__list" data-md-scrollfix>
@@ -659,7 +665,7 @@
<span class="md-ellipsis">
2.1 Algorithm Efficiency Assessment
2.1 Algorithm efficiency assessment
</span>
@@ -680,7 +686,7 @@
<span class="md-ellipsis">
2.2 Iteration and Recursion
2.2 Iteration and recursion
</span>
@@ -701,7 +707,7 @@
<span class="md-ellipsis">
2.3 Time Complexity
2.3 Time complexity
</span>
@@ -722,7 +728,7 @@
<span class="md-ellipsis">
2.4 Space Complexity
2.4 Space complexity
</span>
@@ -803,7 +809,7 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M11 13.5v8H3v-8h8m-2 2H5v4h4v-4M12 2l5.5 9h-11L12 2m0 3.86L10.08 9h3.84L12 5.86M17.5 13c2.5 0 4.5 2 4.5 4.5S20 22 17.5 22 13 20 13 17.5s2-4.5 4.5-4.5m0 2a2.5 2.5 0 0 0-2.5 2.5 2.5 2.5 0 0 0 2.5 2.5 2.5 2.5 0 0 0 2.5-2.5 2.5 2.5 0 0 0-2.5-2.5Z"/></svg>
<span class="md-ellipsis">
Chapter 3. Data Structures
Chapter 3. Data structures
</span>
@@ -819,7 +825,7 @@
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_4_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_4">
<span class="md-nav__icon md-icon"></span>
Chapter 3. Data Structures
Chapter 3. Data structures
</label>
<ul class="md-nav__list" data-md-scrollfix>
@@ -836,7 +842,7 @@
<span class="md-ellipsis">
3.1 Classification of Data Structures
3.1 Classification of data structures
</span>
@@ -857,7 +863,7 @@
<span class="md-ellipsis">
3.2 Fundamental Data Types
3.2 Fundamental data types
</span>
@@ -878,7 +884,7 @@
<span class="md-ellipsis">
3.3 Number Encoding *
3.3 Number encoding *
</span>
@@ -899,7 +905,7 @@
<span class="md-ellipsis">
3.4 Character Encoding *
3.4 Character encoding *
</span>
@@ -980,7 +986,7 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 5v14h17V5H3m4 2v2H5V7h2m-2 6v-2h2v2H5m0 2h2v2H5v-2m13 2H9v-2h9v2m0-4H9v-2h9v2m0-4H9V7h9v2Z"/></svg>
<span class="md-ellipsis">
Chapter 4. Array and Linked List
Chapter 4. Array and linked list
</span>
@@ -996,7 +1002,7 @@
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_5">
<span class="md-nav__icon md-icon"></span>
Chapter 4. Array and Linked List
Chapter 4. Array and linked list
</label>
<ul class="md-nav__list" data-md-scrollfix>
@@ -1034,7 +1040,7 @@
<span class="md-ellipsis">
4.2 Linked List
4.2 Linked list
</span>
@@ -1076,7 +1082,7 @@
<span class="md-ellipsis">
4.4 Memory and Cache
4.4 Memory and cache
</span>
@@ -1157,7 +1163,7 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M17.36 20.2v-5.38h1.79V22H3v-7.18h1.8v5.38h12.56M6.77 14.32l.37-1.76 8.79 1.85-.37 1.76-8.79-1.85m1.16-4.21.76-1.61 8.14 3.78-.76 1.62-8.14-3.79m2.26-3.99 1.15-1.38 6.9 5.76-1.15 1.37-6.9-5.75m4.45-4.25L20 9.08l-1.44 1.07-5.36-7.21 1.44-1.07M6.59 18.41v-1.8h8.98v1.8H6.59Z"/></svg>
<span class="md-ellipsis">
Chapter 5. Stack and Queue
Chapter 5. Stack and queue
</span>
@@ -1173,7 +1179,7 @@
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_6_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_6">
<span class="md-nav__icon md-icon"></span>
Chapter 5. Stack and Queue
Chapter 5. Stack and queue
</label>
<ul class="md-nav__list" data-md-scrollfix>
@@ -1241,7 +1247,7 @@
<span class="md-ellipsis">
5.3 Double-ended Queue
5.3 Double-ended queue
</span>
@@ -1252,7 +1258,7 @@
<span class="md-ellipsis">
5.3 Double-ended Queue
5.3 Double-ended queue
</span>
@@ -1276,7 +1282,7 @@
<li class="md-nav__item">
<a href="#531-common-operations-in-double-ended-queue" class="md-nav__link">
<span class="md-ellipsis">
5.3.1 &nbsp; Common Operations in Double-Ended Queue
5.3.1 &nbsp; Common operations in double-ended queue
</span>
</a>
@@ -1285,17 +1291,17 @@
<li class="md-nav__item">
<a href="#532-implementing-a-double-ended-queue" class="md-nav__link">
<span class="md-ellipsis">
5.3.2 &nbsp; Implementing a Double-Ended Queue *
5.3.2 &nbsp; Implementing a double-ended queue *
</span>
</a>
<nav class="md-nav" aria-label="5.3.2   Implementing a Double-Ended Queue *">
<nav class="md-nav" aria-label="5.3.2   Implementing a double-ended queue *">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#1-implementation-based-on-doubly-linked-list" class="md-nav__link">
<span class="md-ellipsis">
1. &nbsp; Implementation Based on Doubly Linked List
1. &nbsp; Implementation based on doubly linked list
</span>
</a>
@@ -1304,7 +1310,7 @@
<li class="md-nav__item">
<a href="#2-implementation-based-on-array" class="md-nav__link">
<span class="md-ellipsis">
2. &nbsp; Implementation Based on Array
2. &nbsp; Implementation based on array
</span>
</a>
@@ -1318,7 +1324,7 @@
<li class="md-nav__item">
<a href="#533-applications-of-double-ended-queue" class="md-nav__link">
<span class="md-ellipsis">
5.3.3 &nbsp; Applications of Double-Ended Queue
5.3.3 &nbsp; Applications of double-ended queue
</span>
</a>
@@ -1402,7 +1408,7 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19.3 17.89c1.32-2.1.7-4.89-1.41-6.21a4.52 4.52 0 0 0-6.21 1.41C10.36 15.2 11 18 13.09 19.3c1.47.92 3.33.92 4.8 0L21 22.39 22.39 21l-3.09-3.11m-2-.62c-.98.98-2.56.97-3.54 0-.97-.98-.97-2.56.01-3.54.97-.97 2.55-.97 3.53 0 .96.99.95 2.57-.03 3.54h.03M19 4H5a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h5.81a6.3 6.3 0 0 1-1.31-2H5v-4h4.18c.16-.71.43-1.39.82-2H5V8h6v2.81a6.3 6.3 0 0 1 2-1.31V8h6v2a6.499 6.499 0 0 1 2 2V6a2 2 0 0 0-2-2Z"/></svg>
<span class="md-ellipsis">
Chapter 6. Hash Table
Chapter 6. Hash table
</span>
@@ -1418,7 +1424,7 @@
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_7_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_7">
<span class="md-nav__icon md-icon"></span>
Chapter 6. Hash Table
Chapter 6. Hash table
</label>
<ul class="md-nav__list" data-md-scrollfix>
@@ -1435,7 +1441,7 @@
<span class="md-ellipsis">
6.1 Hash Table
6.1 Hash table
</span>
@@ -1456,7 +1462,7 @@
<span class="md-ellipsis">
6.2 Hash Collision
6.2 Hash collision
</span>
@@ -1477,7 +1483,7 @@
<span class="md-ellipsis">
6.3 Hash Algorithm
6.3 Hash algorithm
</span>
@@ -2052,7 +2058,7 @@
<li class="md-nav__item">
<a href="#531-common-operations-in-double-ended-queue" class="md-nav__link">
<span class="md-ellipsis">
5.3.1 &nbsp; Common Operations in Double-Ended Queue
5.3.1 &nbsp; Common operations in double-ended queue
</span>
</a>
@@ -2061,17 +2067,17 @@
<li class="md-nav__item">
<a href="#532-implementing-a-double-ended-queue" class="md-nav__link">
<span class="md-ellipsis">
5.3.2 &nbsp; Implementing a Double-Ended Queue *
5.3.2 &nbsp; Implementing a double-ended queue *
</span>
</a>
<nav class="md-nav" aria-label="5.3.2   Implementing a Double-Ended Queue *">
<nav class="md-nav" aria-label="5.3.2   Implementing a double-ended queue *">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#1-implementation-based-on-doubly-linked-list" class="md-nav__link">
<span class="md-ellipsis">
1. &nbsp; Implementation Based on Doubly Linked List
1. &nbsp; Implementation based on doubly linked list
</span>
</a>
@@ -2080,7 +2086,7 @@
<li class="md-nav__item">
<a href="#2-implementation-based-on-array" class="md-nav__link">
<span class="md-ellipsis">
2. &nbsp; Implementation Based on Array
2. &nbsp; Implementation based on array
</span>
</a>
@@ -2094,7 +2100,7 @@
<li class="md-nav__item">
<a href="#533-applications-of-double-ended-queue" class="md-nav__link">
<span class="md-ellipsis">
5.3.3 &nbsp; Applications of Double-Ended Queue
5.3.3 &nbsp; Applications of double-ended queue
</span>
</a>
@@ -2136,14 +2142,14 @@
<!-- Page content -->
<h1 id="53-double-ended-queue">5.3 &nbsp; Double-Ended Queue<a class="headerlink" href="#53-double-ended-queue" title="Permanent link">&para;</a></h1>
<h1 id="53-double-ended-queue">5.3 &nbsp; Double-ended queue<a class="headerlink" href="#53-double-ended-queue" title="Permanent link">&para;</a></h1>
<p>In a queue, we can only delete elements from the head or add elements to the tail. As shown in the following diagram, a "double-ended queue (deque)" offers more flexibility, allowing the addition or removal of elements at both the head and the tail.</p>
<p><a class="glightbox" href="../deque.assets/deque_operations.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="Operations in Double-Ended Queue" class="animation-figure" src="../deque.assets/deque_operations.png" /></a></p>
<p align="center"> Figure 5-7 &nbsp; Operations in Double-Ended Queue </p>
<p><a class="glightbox" href="../deque.assets/deque_operations.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="Operations in double-ended queue" class="animation-figure" src="../deque.assets/deque_operations.png" /></a></p>
<p align="center"> Figure 5-7 &nbsp; Operations in double-ended queue </p>
<h2 id="531-common-operations-in-double-ended-queue">5.3.1 &nbsp; Common Operations in Double-Ended Queue<a class="headerlink" href="#531-common-operations-in-double-ended-queue" title="Permanent link">&para;</a></h2>
<h2 id="531-common-operations-in-double-ended-queue">5.3.1 &nbsp; Common operations in double-ended queue<a class="headerlink" href="#531-common-operations-in-double-ended-queue" title="Permanent link">&para;</a></h2>
<p>The common operations in a double-ended queue are listed below, and the names of specific methods depend on the programming language used.</p>
<p align="center"> Table 5-3 &nbsp; Efficiency of Double-Ended Queue Operations </p>
<p align="center"> Table 5-3 &nbsp; Efficiency of double-ended queue operations </p>
<div class="center-table">
<table>
@@ -2486,9 +2492,9 @@
<summary>Visualizing Code</summary>
<p>https://pythontutor.com/render.html#code=from%20collections%20import%20deque%0A%0A%22%22%22Driver%20Code%22%22%22%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20%23%20%E5%88%9D%E5%A7%8B%E5%8C%96%E5%8F%8C%E5%90%91%E9%98%9F%E5%88%97%0A%20%20%20%20deq%20%3D%20deque%28%29%0A%0A%20%20%20%20%23%20%E5%85%83%E7%B4%A0%E5%85%A5%E9%98%9F%0A%20%20%20%20deq.append%282%29%20%20%23%20%E6%B7%BB%E5%8A%A0%E8%87%B3%E9%98%9F%E5%B0%BE%0A%20%20%20%20deq.append%285%29%0A%20%20%20%20deq.append%284%29%0A%20%20%20%20deq.appendleft%283%29%20%20%23%20%E6%B7%BB%E5%8A%A0%E8%87%B3%E9%98%9F%E9%A6%96%0A%20%20%20%20deq.appendleft%281%29%0A%20%20%20%20print%28%22%E5%8F%8C%E5%90%91%E9%98%9F%E5%88%97%20deque%20%3D%22,%20deq%29%0A%0A%20%20%20%20%23%20%E8%AE%BF%E9%97%AE%E5%85%83%E7%B4%A0%0A%20%20%20%20front%20%3D%20deq%5B0%5D%20%20%23%20%E9%98%9F%E9%A6%96%E5%85%83%E7%B4%A0%0A%20%20%20%20print%28%22%E9%98%9F%E9%A6%96%E5%85%83%E7%B4%A0%20front%20%3D%22,%20front%29%0A%20%20%20%20rear%20%3D%20deq%5B-1%5D%20%20%23%20%E9%98%9F%E5%B0%BE%E5%85%83%E7%B4%A0%0A%20%20%20%20print%28%22%E9%98%9F%E5%B0%BE%E5%85%83%E7%B4%A0%20rear%20%3D%22,%20rear%29%0A%0A%20%20%20%20%23%20%E5%85%83%E7%B4%A0%E5%87%BA%E9%98%9F%0A%20%20%20%20pop_front%20%3D%20deq.popleft%28%29%20%20%23%20%E9%98%9F%E9%A6%96%E5%85%83%E7%B4%A0%E5%87%BA%E9%98%9F%0A%20%20%20%20print%28%22%E9%98%9F%E9%A6%96%E5%87%BA%E9%98%9F%E5%85%83%E7%B4%A0%20%20pop_front%20%3D%22,%20pop_front%29%0A%20%20%20%20print%28%22%E9%98%9F%E9%A6%96%E5%87%BA%E9%98%9F%E5%90%8E%20deque%20%3D%22,%20deq%29%0A%20%20%20%20pop_rear%20%3D%20deq.pop%28%29%20%20%23%20%E9%98%9F%E5%B0%BE%E5%85%83%E7%B4%A0%E5%87%BA%E9%98%9F%0A%20%20%20%20print%28%22%E9%98%9F%E5%B0%BE%E5%87%BA%E9%98%9F%E5%85%83%E7%B4%A0%20%20pop_rear%20%3D%22,%20pop_rear%29%0A%20%20%20%20print%28%22%E9%98%9F%E5%B0%BE%E5%87%BA%E9%98%9F%E5%90%8E%20deque%20%3D%22,%20deq%29%0A%0A%20%20%20%20%23%20%E8%8E%B7%E5%8F%96%E5%8F%8C%E5%90%91%E9%98%9F%E5%88%97%E7%9A%84%E9%95%BF%E5%BA%A6%0A%20%20%20%20size%20%3D%20len%28deq%29%0A%20%20%20%20print%28%22%E5%8F%8C%E5%90%91%E9%98%9F%E5%88%97%E9%95%BF%E5%BA%A6%20size%20%3D%22,%20size%29%0A%0A%20%20%20%20%23%20%E5%88%A4%E6%96%AD%E5%8F%8C%E5%90%91%E9%98%9F%E5%88%97%E6%98%AF%E5%90%A6%E4%B8%BA%E7%A9%BA%0A%20%20%20%20is_empty%20%3D%20len%28deq%29%20%3D%3D%200%0A%20%20%20%20print%28%22%E5%8F%8C%E5%90%91%E9%98%9F%E5%88%97%E6%98%AF%E5%90%A6%E4%B8%BA%E7%A9%BA%20%3D%22,%20is_empty%29&amp;cumulative=false&amp;curInstr=3&amp;heapPrimitives=nevernest&amp;mode=display&amp;origin=opt-frontend.js&amp;py=311&amp;rawInputLstJSON=%5B%5D&amp;textReferences=false</p>
</details>
<h2 id="532-implementing-a-double-ended-queue">5.3.2 &nbsp; Implementing a Double-Ended Queue *<a class="headerlink" href="#532-implementing-a-double-ended-queue" title="Permanent link">&para;</a></h2>
<h2 id="532-implementing-a-double-ended-queue">5.3.2 &nbsp; Implementing a double-ended queue *<a class="headerlink" href="#532-implementing-a-double-ended-queue" title="Permanent link">&para;</a></h2>
<p>The implementation of a double-ended queue is similar to that of a regular queue, it can be based on either a linked list or an array as the underlying data structure.</p>
<h3 id="1-implementation-based-on-doubly-linked-list">1. &nbsp; Implementation Based on Doubly Linked List<a class="headerlink" href="#1-implementation-based-on-doubly-linked-list" title="Permanent link">&para;</a></h3>
<h3 id="1-implementation-based-on-doubly-linked-list">1. &nbsp; Implementation based on doubly linked list<a class="headerlink" href="#1-implementation-based-on-doubly-linked-list" title="Permanent link">&para;</a></h3>
<p>Recall from the previous section that we used a regular singly linked list to implement a queue, as it conveniently allows for deleting from the head (corresponding to the dequeue operation) and adding new elements after the tail (corresponding to the enqueue operation).</p>
<p>For a double-ended queue, both the head and the tail can perform enqueue and dequeue operations. In other words, a double-ended queue needs to implement operations in the opposite direction as well. For this, we use a "doubly linked list" as the underlying data structure of the double-ended queue.</p>
<p>As shown in the Figure 5-8 , we treat the head and tail nodes of the doubly linked list as the front and rear of the double-ended queue, respectively, and implement the functionality to add and remove nodes at both ends.</p>
@@ -4245,7 +4251,7 @@
</div>
</div>
</div>
<h3 id="2-implementation-based-on-array">2. &nbsp; Implementation Based on Array<a class="headerlink" href="#2-implementation-based-on-array" title="Permanent link">&para;</a></h3>
<h3 id="2-implementation-based-on-array">2. &nbsp; Implementation based on array<a class="headerlink" href="#2-implementation-based-on-array" title="Permanent link">&para;</a></h3>
<p>As shown in the Figure 5-9 , similar to implementing a queue with an array, we can also use a circular array to implement a double-ended queue.</p>
<div class="tabbed-set tabbed-alternate" data-tabs="4:5"><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" /><input id="__tabbed_4_5" name="__tabbed_4" type="radio" /><div class="tabbed-labels"><label for="__tabbed_4_1">ArrayDeque</label><label for="__tabbed_4_2">pushLast()</label><label for="__tabbed_4_3">pushFirst()</label><label for="__tabbed_4_4">popLast()</label><label for="__tabbed_4_5">popFirst()</label></div>
<div class="tabbed-content">
@@ -5556,7 +5562,7 @@
</div>
</div>
</div>
<h2 id="533-applications-of-double-ended-queue">5.3.3 &nbsp; Applications of Double-Ended Queue<a class="headerlink" href="#533-applications-of-double-ended-queue" title="Permanent link">&para;</a></h2>
<h2 id="533-applications-of-double-ended-queue">5.3.3 &nbsp; Applications of double-ended queue<a class="headerlink" href="#533-applications-of-double-ended-queue" title="Permanent link">&para;</a></h2>
<p>The double-ended queue combines the logic of both stacks and queues, <strong>thus, it can implement all their respective use cases while offering greater flexibility</strong>.</p>
<p>We know that software's "undo" feature is typically implemented using a stack: the system <code>pushes</code> each change operation onto the stack and then <code>pops</code> to implement undoing. However, considering the limitations of system resources, software often restricts the number of undo steps (for example, only allowing the last 50 steps). When the stack length exceeds 50, the software needs to perform a deletion operation at the bottom of the stack (the front of the queue). <strong>But a regular stack cannot perform this function, where a double-ended queue becomes necessary</strong>. Note that the core logic of "undo" still follows the Last-In-First-Out principle of a stack, but a double-ended queue can more flexibly implement some additional logic.</p>