forked from krahets/hello-algo
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add array_deque.py and linkedlist_deque.py (krahets#399)
- Loading branch information
Showing
2 changed files
with
279 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
""" | ||
File: array_deque.py | ||
Created Time: 2023-03-01 | ||
Author: Krahets ([email protected]) | ||
""" | ||
|
||
import os.path as osp | ||
import sys | ||
|
||
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__)))) | ||
from include import * | ||
|
||
""" 基于环形数组实现的双向队列 """ | ||
class ArrayDeque: | ||
""" 构造方法 """ | ||
def __init__(self, capacity): | ||
self.nums = [0] * capacity | ||
self.front = 0 | ||
self.que_size = 0 | ||
|
||
""" 获取双向队列的容量 """ | ||
def capacity(self): | ||
return len(self.nums) | ||
|
||
""" 获取双向队列的长度 """ | ||
def size(self): | ||
return self.que_size | ||
|
||
""" 判断双向队列是否为空 """ | ||
def is_empty(self): | ||
return self.que_size == 0 | ||
|
||
""" 计算环形数组索引 """ | ||
def index(self, i): | ||
# 通过取余操作实现数组首尾相连 | ||
# 当 i 越过数组尾部后,回到头部 | ||
# 当 i 越过数组头部后,回到尾部 | ||
return (i + self.capacity()) % self.capacity() | ||
|
||
""" 队首入队 """ | ||
def push_first(self, num): | ||
if self.que_size == self.capacity(): | ||
print("双向队列已满") | ||
return | ||
# 队首指针向左移动一位 | ||
# 通过取余操作,实现 front 越过数组头部后回到尾部 | ||
self.front = self.index(self.front-1) | ||
# 将 num 添加至队首 | ||
self.nums[self.front] = num | ||
self.que_size += 1 | ||
|
||
""" 队尾入队 """ | ||
def push_last(self, num): | ||
if self.que_size == self.capacity(): | ||
print("双向队列已满") | ||
return | ||
# 计算尾指针,指向队尾索引 + 1 | ||
rear = self.index(self.front + self.que_size) | ||
# 将 num 添加至队尾 | ||
self.nums[rear] = num | ||
self.que_size += 1 | ||
|
||
""" 队首出队 """ | ||
def poll_first(self): | ||
num = self.peek_first() | ||
# 队首指针向后移动一位 | ||
self.front = self.index(self.front+1) | ||
self.que_size -= 1 | ||
return num | ||
|
||
""" 队尾出队 """ | ||
def poll_last(self): | ||
num = self.peek_last() | ||
self.que_size -= 1 | ||
return num | ||
|
||
""" 访问队首元素 """ | ||
def peek_first(self): | ||
assert not self.is_empty(), "双向队列为空" | ||
return self.nums[self.front] | ||
|
||
""" 访问队尾元素 """ | ||
def peek_last(self): | ||
assert not self.is_empty(), "双向队列为空" | ||
# 计算尾元素索引 | ||
last = self.index(self.front + self.que_size - 1) | ||
return self.nums[last] | ||
|
||
""" 返回数组用于打印 """ | ||
def to_array(self): | ||
# 仅转换有效长度范围内的列表元素 | ||
res = [] | ||
for i in range(self.que_size): | ||
res.append(self.nums[self.index(self.front+i)]) | ||
return res | ||
|
||
|
||
""" Driver Code """ | ||
if __name__ == "__main__": | ||
""" 初始化双向队列 """ | ||
deque = ArrayDeque(10) | ||
deque.push_last(3) | ||
deque.push_last(2) | ||
deque.push_last(5) | ||
print("双向队列 deque =", deque.to_array()) | ||
|
||
""" 访问元素 """ | ||
peek_first = deque.peek_first() | ||
print("队首元素 peek_first =", peek_first) | ||
peek_last = deque.peek_last() | ||
print("队尾元素 peek_last =", peek_last) | ||
|
||
""" 元素入队 """ | ||
deque.push_last(4) | ||
print("元素 4 队尾入队后 deque =", deque.to_array()) | ||
deque.push_first(1) | ||
print("元素 1 队首入队后 deque =", deque.to_array()) | ||
|
||
""" 元素出队 """ | ||
poll_last = deque.poll_last() | ||
print("队尾出队元素 =", poll_last, ",队尾出队后 deque =", deque.to_array()) | ||
poll_first = deque.poll_first() | ||
print("队首出队元素 =", poll_first, ",队首出队后 deque =", deque.to_array()) | ||
|
||
""" 获取双向队列的长度 """ | ||
size = deque.size() | ||
print("双向队列长度 size =", size) | ||
|
||
""" 判断双向队列是否为空 """ | ||
is_empty = deque.is_empty() | ||
print("双向队列是否为空 =", is_empty) |
148 changes: 148 additions & 0 deletions
148
codes/python/chapter_stack_and_queue/linkedlist_deque.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
""" | ||
File: linkedlist_deque.py | ||
Created Time: 2023-03-01 | ||
Author: Krahets ([email protected]) | ||
""" | ||
|
||
import os.path as osp | ||
import sys | ||
|
||
sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__)))) | ||
from include import * | ||
|
||
""" 双向链表结点 """ | ||
class ListNode: | ||
def __init__(self, val): | ||
self.val = val | ||
self.next = None # 后继结点引用(指针) | ||
self.prev = None # 前驱结点引用(指针) | ||
|
||
""" 基于双向链表实现的双向队列 """ | ||
class LinkedListDeque: | ||
""" 构造方法 """ | ||
def __init__(self): | ||
self.front, self.rear = None, None # 头结点 front ,尾结点 rear | ||
self.__size = 0 # 双向队列的长度 | ||
|
||
""" 获取双向队列的长度 """ | ||
def size(self): | ||
return self.__size | ||
|
||
""" 判断双向队列是否为空 """ | ||
def is_empty(self): | ||
return self.size() == 0 | ||
|
||
""" 入队操作 """ | ||
def push(self, num, is_front): | ||
node = ListNode(num) | ||
# 若链表为空,则令 front, rear 都指向 node | ||
if self.is_empty(): | ||
self.front = self.rear = node | ||
# 队首入队操作 | ||
elif is_front: | ||
# 将 node 添加至链表头部 | ||
self.front.prev = node | ||
node.next = self.front | ||
self.front = node # 更新头结点 | ||
# 队尾入队操作 | ||
else: | ||
# 将 node 添加至链表尾部 | ||
self.rear.next = node | ||
node.prev = self.rear | ||
self.rear = node # 更新尾结点 | ||
self.__size += 1 # 更新队列长度 | ||
|
||
""" 队首入队 """ | ||
def push_first(self, num): | ||
self.push(num, True) | ||
|
||
""" 队尾入队 """ | ||
def push_last(self, num): | ||
self.push(num, False) | ||
|
||
""" 出队操作 """ | ||
def poll(self, is_front): | ||
# 若队列为空,直接返回 None | ||
if self.is_empty(): | ||
return None | ||
# 队首出队操作 | ||
if is_front: | ||
val = self.front.val # 暂存头结点值 | ||
# 删除头结点 | ||
fnext = self.front.next | ||
if fnext != None: | ||
fnext.prev = None | ||
self.front.next = None | ||
self.front = fnext # 更新头结点 | ||
# 队尾出队操作 | ||
else: | ||
val = self.rear.val # 暂存尾结点值 | ||
# 删除尾结点 | ||
rprev = self.rear.prev | ||
if rprev != None: | ||
rprev.next = None | ||
self.rear.prev = None | ||
self.rear = rprev # 更新尾结点 | ||
self.__size -= 1 # 更新队列长度 | ||
return val | ||
|
||
""" 队首出队 """ | ||
def poll_first(self): | ||
return self.poll(True) | ||
|
||
""" 队尾出队 """ | ||
def poll_last(self): | ||
return self.poll(False) | ||
|
||
""" 访问队首元素 """ | ||
def peek_first(self): | ||
return None if self.is_empty() else self.front.val | ||
|
||
""" 访问队尾元素 """ | ||
def peek_last(self): | ||
return None if self.is_empty() else self.rear.val | ||
|
||
""" 返回数组用于打印 """ | ||
def to_array(self): | ||
node = self.front | ||
res = [0] * self.size() | ||
for i in range(self.size()): | ||
res[i] = node.val | ||
node = node.next | ||
return res | ||
|
||
|
||
""" Driver Code """ | ||
if __name__ == "__main__": | ||
""" 初始化双向队列 """ | ||
deque = LinkedListDeque() | ||
deque.push_last(3) | ||
deque.push_last(2) | ||
deque.push_last(5) | ||
print("双向队列 deque =", deque.to_array()) | ||
|
||
""" 访问元素 """ | ||
peek_first = deque.peek_first() | ||
print("队首元素 peek_first =", peek_first) | ||
peek_last = deque.peek_last() | ||
print("队尾元素 peek_last =", peek_last) | ||
|
||
""" 元素入队 """ | ||
deque.push_last(4) | ||
print("元素 4 队尾入队后 deque =", deque.to_array()) | ||
deque.push_first(1) | ||
print("元素 1 队首入队后 deque =", deque.to_array()) | ||
|
||
""" 元素出队 """ | ||
poll_last = deque.poll_last() | ||
print("队尾出队元素 =", poll_last, ",队尾出队后 deque =", deque.to_array()) | ||
poll_first = deque.poll_first() | ||
print("队首出队元素 =", poll_first, ",队首出队后 deque =", deque.to_array()) | ||
|
||
""" 获取双向队列的长度 """ | ||
size = deque.size() | ||
print("双向队列长度 size =", size) | ||
|
||
""" 判断双向队列是否为空 """ | ||
is_empty = deque.is_empty() | ||
print("双向队列是否为空 =", is_empty) |