mirror of
https://github.com/krahets/hello-algo.git
synced 2026-04-05 03:30:30 +08:00
build
This commit is contained in:
@@ -149,8 +149,8 @@ elementAddr = firtstElementAddr + elementLength * elementIndex
|
||||
=== "Python"
|
||||
|
||||
```python title="array.py"
|
||||
""" 随机访问元素 """
|
||||
def random_access(nums):
|
||||
""" 随机访问元素 """
|
||||
# 在区间 [0, len(nums)-1] 中随机抽取一个数字
|
||||
random_index = random.randint(0, len(nums) - 1)
|
||||
# 获取并返回随机元素
|
||||
@@ -285,10 +285,8 @@ elementAddr = firtstElementAddr + elementLength * elementIndex
|
||||
=== "Python"
|
||||
|
||||
```python title="array.py"
|
||||
""" 扩展数组长度 """
|
||||
# 请注意,Python 的 list 是动态数组,可以直接扩展
|
||||
# 为了方便学习,本函数将 list 看作是长度不可变的数组
|
||||
def extend(nums, enlarge):
|
||||
""" 扩展数组长度 """
|
||||
# 初始化一个扩展长度后的数组
|
||||
res = [0] * (len(nums) + enlarge)
|
||||
# 将原数组中的所有元素复制到新数组
|
||||
@@ -442,8 +440,8 @@ elementAddr = firtstElementAddr + elementLength * elementIndex
|
||||
=== "Python"
|
||||
|
||||
```python title="array.py"
|
||||
""" 在数组的索引 index 处插入元素 num """
|
||||
def insert(nums, num, index):
|
||||
""" 在数组的索引 index 处插入元素 num """
|
||||
# 把索引 index 以及之后的所有元素向后移动一位
|
||||
for i in range(len(nums) - 1, index, -1):
|
||||
nums[i] = nums[i - 1]
|
||||
@@ -562,8 +560,8 @@ elementAddr = firtstElementAddr + elementLength * elementIndex
|
||||
=== "Python"
|
||||
|
||||
```python title="array.py"
|
||||
""" 删除索引 index 处元素 """
|
||||
def remove(nums, index):
|
||||
""" 删除索引 index 处元素 """
|
||||
# 把索引 index 之后的所有元素向前移动一位
|
||||
for i in range(index, len(nums) - 1):
|
||||
nums[i] = nums[i + 1]
|
||||
@@ -694,8 +692,8 @@ elementAddr = firtstElementAddr + elementLength * elementIndex
|
||||
=== "Python"
|
||||
|
||||
```python title="array.py"
|
||||
""" 遍历数组 """
|
||||
def traverse(nums):
|
||||
""" 遍历数组 """
|
||||
count = 0
|
||||
# 通过索引遍历数组
|
||||
for i in range(len(nums)):
|
||||
@@ -850,8 +848,8 @@ elementAddr = firtstElementAddr + elementLength * elementIndex
|
||||
=== "Python"
|
||||
|
||||
```python title="array.py"
|
||||
""" 在数组中查找指定元素 """
|
||||
def find(nums, target):
|
||||
""" 在数组中查找指定元素 """
|
||||
for i in range(len(nums)):
|
||||
if nums[i] == target:
|
||||
return i
|
||||
|
||||
@@ -351,8 +351,8 @@ comments: true
|
||||
=== "Python"
|
||||
|
||||
```python title="linked_list.py"
|
||||
""" 在链表的结点 n0 之后插入结点 P """
|
||||
def insert(n0, P):
|
||||
""" 在链表的结点 n0 之后插入结点 P """
|
||||
n1 = n0.next
|
||||
P.next = n1
|
||||
n0.next = P
|
||||
@@ -470,8 +470,8 @@ comments: true
|
||||
=== "Python"
|
||||
|
||||
```python title="linked_list.py"
|
||||
""" 删除链表的结点 n0 之后的首个结点 """
|
||||
def remove(n0):
|
||||
""" 删除链表的结点 n0 之后的首个结点 """
|
||||
if not n0.next:
|
||||
return
|
||||
# n0 -> P -> n1
|
||||
@@ -609,8 +609,8 @@ comments: true
|
||||
=== "Python"
|
||||
|
||||
```python title="linked_list.py"
|
||||
""" 访问链表中索引为 index 的结点 """
|
||||
def access(head, index):
|
||||
""" 访问链表中索引为 index 的结点 """
|
||||
for _ in range(index):
|
||||
if not head:
|
||||
return None
|
||||
@@ -757,8 +757,8 @@ comments: true
|
||||
=== "Python"
|
||||
|
||||
```python title="linked_list.py"
|
||||
""" 在链表中查找值为 target 的首个结点 """
|
||||
def find(head, target):
|
||||
""" 在链表中查找值为 target 的首个结点 """
|
||||
index = 0
|
||||
while head:
|
||||
if head.val == target:
|
||||
|
||||
@@ -933,40 +933,45 @@ comments: true
|
||||
=== "Python"
|
||||
|
||||
```python title="my_list.py"
|
||||
""" 列表类简易实现 """
|
||||
class MyList:
|
||||
""" 构造方法 """
|
||||
""" 列表类简易实现 """
|
||||
def __init__(self):
|
||||
""" 构造方法 """
|
||||
self.__capacity = 10 # 列表容量
|
||||
self.__nums = [0] * self.__capacity # 数组(存储列表元素)
|
||||
self.__size = 0 # 列表长度(即当前元素数量)
|
||||
self.__extend_ratio = 2 # 每次列表扩容的倍数
|
||||
|
||||
""" 获取列表长度(即当前元素数量) """
|
||||
def size(self):
|
||||
""" 获取列表长度(即当前元素数量) """
|
||||
return self.__size
|
||||
|
||||
""" 获取列表容量 """
|
||||
def capacity(self):
|
||||
""" 获取列表容量 """
|
||||
return self.__capacity
|
||||
|
||||
""" 访问元素 """
|
||||
def get(self, index):
|
||||
""" 访问元素 """
|
||||
# 索引如果越界则抛出异常,下同
|
||||
assert index >= 0 and index < self.__size, "索引越界"
|
||||
return self.__nums[index]
|
||||
|
||||
""" 更新元素 """
|
||||
def set(self, num, index):
|
||||
""" 更新元素 """
|
||||
assert index >= 0 and index < self.__size, "索引越界"
|
||||
self.__nums[index] = num
|
||||
|
||||
def add(self, num):
|
||||
""" 尾部添加元素 """
|
||||
# 元素数量超出容量时,触发扩容机制
|
||||
if self.size() == self.capacity():
|
||||
self.extend_capacity();
|
||||
self.__nums[self.__size] = num
|
||||
self.__size += 1
|
||||
|
||||
""" 中间插入(尾部添加)元素 """
|
||||
def add(self, num, index=-1):
|
||||
def insert(self, num, index):
|
||||
""" 中间插入元素 """
|
||||
assert index >= 0 and index < self.__size, "索引越界"
|
||||
# 若不指定索引 index ,则向数组尾部添加元素
|
||||
if index == -1:
|
||||
index = self.__size
|
||||
# 元素数量超出容量时,触发扩容机制
|
||||
if self.__size == self.capacity():
|
||||
self.extend_capacity()
|
||||
@@ -977,10 +982,10 @@ comments: true
|
||||
# 更新元素数量
|
||||
self.__size += 1
|
||||
|
||||
""" 删除元素 """
|
||||
def remove(self, index):
|
||||
""" 删除元素 """
|
||||
assert index >= 0 and index < self.__size, "索引越界"
|
||||
num = self.nums[index]
|
||||
num = self.__nums[index]
|
||||
# 索引 i 之后的元素都向前移动一位
|
||||
for j in range(index, self.__size - 1):
|
||||
self.__nums[j] = self.__nums[j + 1]
|
||||
@@ -989,15 +994,15 @@ comments: true
|
||||
# 返回被删除元素
|
||||
return num
|
||||
|
||||
""" 列表扩容 """
|
||||
def extend_capacity(self):
|
||||
""" 列表扩容 """
|
||||
# 新建一个长度为 self.__size 的数组,并将原数组拷贝到新数组
|
||||
self.__nums = self.__nums + [0] * self.capacity() * (self.__extend_ratio - 1)
|
||||
# 更新列表容量
|
||||
self.__capacity = len(self.__nums)
|
||||
|
||||
""" 返回有效长度的列表 """
|
||||
def to_array(self):
|
||||
""" 返回有效长度的列表 """
|
||||
return self.__nums[:self.__size]
|
||||
```
|
||||
|
||||
@@ -1311,7 +1316,7 @@ comments: true
|
||||
public toArray(): number[] {
|
||||
let size = this.size();
|
||||
// 仅转换有效长度范围内的列表元素
|
||||
let nums = new Array(size);
|
||||
const nums = new Array(size);
|
||||
for (let i = 0; i < size; i++) {
|
||||
nums[i] = this.get(i);
|
||||
}
|
||||
|
||||
@@ -624,8 +624,8 @@ $$
|
||||
=== "Python"
|
||||
|
||||
```python title="space_complexity.py"
|
||||
""" 常数阶 """
|
||||
def constant(n):
|
||||
""" 常数阶 """
|
||||
# 常量、变量、对象占用 O(1) 空间
|
||||
a = 0
|
||||
nums = [0] * 10000
|
||||
@@ -829,8 +829,8 @@ $$
|
||||
=== "Python"
|
||||
|
||||
```python title="space_complexity.py"
|
||||
""" 线性阶 """
|
||||
def linear(n):
|
||||
""" 线性阶 """
|
||||
# 长度为 n 的列表占用 O(n) 空间
|
||||
nums = [0] * n
|
||||
# 长度为 n 的哈希表占用 O(n) 空间
|
||||
@@ -996,8 +996,8 @@ $$
|
||||
=== "Python"
|
||||
|
||||
```python title="space_complexity.py"
|
||||
""" 线性阶(递归实现) """
|
||||
def linear_recur(n):
|
||||
""" 线性阶(递归实现) """
|
||||
print("递归 n =", n)
|
||||
if n == 1: return
|
||||
linear_recur(n - 1)
|
||||
@@ -1127,8 +1127,8 @@ $$
|
||||
=== "Python"
|
||||
|
||||
```python title="space_complexity.py"
|
||||
""" 平方阶 """
|
||||
def quadratic(n):
|
||||
""" 平方阶 """
|
||||
# 二维列表占用 O(n^2) 空间
|
||||
num_matrix = [[0] * n for _ in range(n)]
|
||||
```
|
||||
@@ -1171,7 +1171,9 @@ $$
|
||||
/* 平方阶 */
|
||||
function quadratic(n: number): void {
|
||||
// 矩阵占用 O(n^2) 空间
|
||||
const numMatrix = Array(n).fill(null).map(() => Array(n).fill(null));
|
||||
const numMatrix = Array(n)
|
||||
.fill(null)
|
||||
.map(() => Array(n).fill(null));
|
||||
// 二维列表占用 O(n^2) 空间
|
||||
const numList = [];
|
||||
for (let i = 0; i < n; i++) {
|
||||
@@ -1273,8 +1275,8 @@ $$
|
||||
=== "Python"
|
||||
|
||||
```python title="space_complexity.py"
|
||||
""" 平方阶(递归实现) """
|
||||
def quadratic_recur(n):
|
||||
""" 平方阶(递归实现) """
|
||||
if n <= 0: return 0
|
||||
# 数组 nums 长度为 n, n-1, ..., 2, 1
|
||||
nums = [0] * n
|
||||
@@ -1403,8 +1405,8 @@ $$
|
||||
=== "Python"
|
||||
|
||||
```python title="space_complexity.py"
|
||||
""" 指数阶(建立满二叉树) """
|
||||
def build_tree(n):
|
||||
""" 指数阶(建立满二叉树) """
|
||||
if n == 0: return None
|
||||
root = TreeNode(0)
|
||||
root.left = build_tree(n - 1)
|
||||
|
||||
@@ -65,8 +65,8 @@ comments: true
|
||||
=== "Python"
|
||||
|
||||
```python title="leetcode_two_sum.py"
|
||||
""" 方法一:暴力枚举 """
|
||||
def two_sum_brute_force(nums: List[int], target: int) -> List[int]:
|
||||
""" 方法一:暴力枚举 """
|
||||
# 两层循环,时间复杂度 O(n^2)
|
||||
for i in range(len(nums) - 1):
|
||||
for j in range(i + 1, len(nums)):
|
||||
@@ -242,8 +242,8 @@ comments: true
|
||||
=== "Python"
|
||||
|
||||
```python title="leetcode_two_sum.py"
|
||||
""" 方法二:辅助哈希表 """
|
||||
def two_sum_hash_table(nums: List[int], target: int) -> List[int]:
|
||||
""" 方法二:辅助哈希表 """
|
||||
# 辅助哈希表,空间复杂度 O(n)
|
||||
dic = {}
|
||||
# 单层循环,时间复杂度 O(n)
|
||||
|
||||
@@ -821,8 +821,8 @@ $$
|
||||
=== "Python"
|
||||
|
||||
```python title="time_complexity.py"
|
||||
""" 常数阶 """
|
||||
def constant(n):
|
||||
""" 常数阶 """
|
||||
count = 0
|
||||
size = 100000
|
||||
for _ in range(size):
|
||||
@@ -949,8 +949,8 @@ $$
|
||||
=== "Python"
|
||||
|
||||
```python title="time_complexity.py"
|
||||
""" 线性阶 """
|
||||
def linear(n):
|
||||
""" 线性阶 """
|
||||
count = 0
|
||||
for _ in range(n):
|
||||
count += 1
|
||||
@@ -1075,8 +1075,8 @@ $$
|
||||
=== "Python"
|
||||
|
||||
```python title="time_complexity.py"
|
||||
""" 线性阶(遍历数组)"""
|
||||
def array_traversal(nums):
|
||||
""" 线性阶(遍历数组)"""
|
||||
count = 0
|
||||
# 循环次数与数组长度成正比
|
||||
for num in nums:
|
||||
@@ -1215,8 +1215,8 @@ $$
|
||||
=== "Python"
|
||||
|
||||
```python title="time_complexity.py"
|
||||
""" 平方阶 """
|
||||
def quadratic(n):
|
||||
""" 平方阶 """
|
||||
count = 0
|
||||
# 循环次数与数组长度成平方关系
|
||||
for i in range(n):
|
||||
@@ -1391,8 +1391,8 @@ $$
|
||||
=== "Python"
|
||||
|
||||
```python title="time_complexity.py"
|
||||
""" 平方阶(冒泡排序)"""
|
||||
def bubble_sort(nums):
|
||||
""" 平方阶(冒泡排序)"""
|
||||
count = 0 # 计数器
|
||||
# 外循环:待排序元素数量为 n-1, n-2, ..., 1
|
||||
for i in range(len(nums) - 1, 0, -1):
|
||||
@@ -1604,8 +1604,8 @@ $$
|
||||
=== "Python"
|
||||
|
||||
```python title="time_complexity.py"
|
||||
""" 指数阶(循环实现)"""
|
||||
def exponential(n):
|
||||
""" 指数阶(循环实现)"""
|
||||
count, base = 0, 1
|
||||
# cell 每轮一分为二,形成数列 1, 2, 4, 8, ..., 2^(n-1)
|
||||
for _ in range(n):
|
||||
@@ -1768,8 +1768,8 @@ $$
|
||||
=== "Python"
|
||||
|
||||
```python title="time_complexity.py"
|
||||
""" 指数阶(递归实现)"""
|
||||
def exp_recur(n):
|
||||
""" 指数阶(递归实现)"""
|
||||
if n == 1: return 1
|
||||
return exp_recur(n - 1) + exp_recur(n - 1) + 1
|
||||
```
|
||||
@@ -1884,8 +1884,8 @@ $$
|
||||
=== "Python"
|
||||
|
||||
```python title="time_complexity.py"
|
||||
""" 对数阶(循环实现)"""
|
||||
def logarithmic(n):
|
||||
""" 对数阶(循环实现)"""
|
||||
count = 0
|
||||
while n > 1:
|
||||
n = n / 2
|
||||
@@ -2017,8 +2017,8 @@ $$
|
||||
=== "Python"
|
||||
|
||||
```python title="time_complexity.py"
|
||||
""" 对数阶(递归实现)"""
|
||||
def log_recur(n):
|
||||
""" 对数阶(递归实现)"""
|
||||
if n <= 1: return 0
|
||||
return log_recur(n / 2) + 1
|
||||
```
|
||||
@@ -2133,8 +2133,8 @@ $$
|
||||
=== "Python"
|
||||
|
||||
```python title="time_complexity.py"
|
||||
""" 线性对数阶 """
|
||||
def linear_log_recur(n):
|
||||
""" 线性对数阶 """
|
||||
if n <= 1: return 1
|
||||
count = linear_log_recur(n // 2) + \
|
||||
linear_log_recur(n // 2)
|
||||
@@ -2290,8 +2290,8 @@ $$
|
||||
=== "Python"
|
||||
|
||||
```python title="time_complexity.py"
|
||||
""" 阶乘阶(递归实现)"""
|
||||
def factorial_recur(n):
|
||||
""" 阶乘阶(递归实现)"""
|
||||
if n == 0: return 1
|
||||
count = 0
|
||||
# 从 1 个分裂出 n 个
|
||||
@@ -2480,16 +2480,16 @@ $$
|
||||
=== "Python"
|
||||
|
||||
```python title="worst_best_time_complexity.py"
|
||||
""" 生成一个数组,元素为: 1, 2, ..., n ,顺序被打乱 """
|
||||
def random_numbers(n):
|
||||
""" 生成一个数组,元素为: 1, 2, ..., n ,顺序被打乱 """
|
||||
# 生成数组 nums =: 1, 2, 3, ..., n
|
||||
nums = [i for i in range(1, n + 1)]
|
||||
# 随机打乱数组元素
|
||||
random.shuffle(nums)
|
||||
return nums
|
||||
|
||||
""" 查找数组 nums 中数字 1 所在索引 """
|
||||
def find_one(nums):
|
||||
""" 查找数组 nums 中数字 1 所在索引 """
|
||||
for i in range(len(nums)):
|
||||
# 当元素 1 在数组头部时,达到最佳时间复杂度 O(1)
|
||||
# 当元素 1 在数组尾部时,达到最差时间复杂度 O(n)
|
||||
|
||||
@@ -127,8 +127,8 @@ comments: true
|
||||
```cpp title="graph_adjacency_matrix.cpp"
|
||||
/* 基于邻接矩阵实现的无向图类 */
|
||||
class GraphAdjMat {
|
||||
vector<int> vertices; // 顶点列表,元素代表“顶点值”,索引代表“顶点索引”
|
||||
vector<vector<int>> adjMat; // 邻接矩阵,行列索引对应“顶点索引”
|
||||
vector<int> vertices; // 顶点列表,元素代表“顶点值”,索引代表“顶点索引”
|
||||
vector<vector<int>> adjMat; // 邻接矩阵,行列索引对应“顶点索引”
|
||||
|
||||
public:
|
||||
/* 构造方法 */
|
||||
@@ -213,15 +213,15 @@ comments: true
|
||||
=== "Python"
|
||||
|
||||
```python title="graph_adjacency_matrix.py"
|
||||
""" 基于邻接矩阵实现的无向图类 """
|
||||
class GraphAdjMat:
|
||||
""" 基于邻接矩阵实现的无向图类 """
|
||||
# 顶点列表,元素代表“顶点值”,索引代表“顶点索引”
|
||||
vertices = []
|
||||
# 邻接矩阵,行列索引对应“顶点索引”
|
||||
adj_mat = []
|
||||
|
||||
""" 构造方法 """
|
||||
def __init__(self, vertices, edges):
|
||||
""" 构造方法 """
|
||||
self.vertices = []
|
||||
self.adj_mat = []
|
||||
# 添加顶点
|
||||
@@ -232,12 +232,12 @@ comments: true
|
||||
for e in edges:
|
||||
self.add_edge(e[0], e[1])
|
||||
|
||||
""" 获取顶点数量 """
|
||||
def size(self):
|
||||
""" 获取顶点数量 """
|
||||
return len(self.vertices)
|
||||
|
||||
""" 添加顶点 """
|
||||
def add_vertex(self, val):
|
||||
""" 添加顶点 """
|
||||
n = self.size()
|
||||
# 向顶点列表中添加新顶点的值
|
||||
self.vertices.append(val)
|
||||
@@ -248,9 +248,8 @@ comments: true
|
||||
for row in self.adj_mat:
|
||||
row.append(0)
|
||||
|
||||
|
||||
""" 删除顶点 """
|
||||
def remove_vertex(self, index):
|
||||
""" 删除顶点 """
|
||||
if index >= self.size():
|
||||
raise IndexError()
|
||||
# 在顶点列表中移除索引 index 的顶点
|
||||
@@ -261,9 +260,9 @@ comments: true
|
||||
for row in self.adj_mat:
|
||||
row.pop(index)
|
||||
|
||||
""" 添加边 """
|
||||
# 参数 i, j 对应 vertices 元素索引
|
||||
def add_edge(self, i, j):
|
||||
""" 添加边 """
|
||||
# 参数 i, j 对应 vertices 元素索引
|
||||
# 索引越界与相等处理
|
||||
if i < 0 or j < 0 or i >= self.size() or j >= self.size() or i == j:
|
||||
raise IndexError()
|
||||
@@ -271,17 +270,17 @@ comments: true
|
||||
self.adj_mat[i][j] = 1
|
||||
self.adj_mat[j][i] = 1
|
||||
|
||||
""" 删除边 """
|
||||
# 参数 i, j 对应 vertices 元素索引
|
||||
def remove_edge(self, i, j):
|
||||
""" 删除边 """
|
||||
# 参数 i, j 对应 vertices 元素索引
|
||||
# 索引越界与相等处理
|
||||
if i < 0 or j < 0 or i >= self.size() or j >= self.size() or i == j:
|
||||
raise IndexError()
|
||||
self.adj_mat[i][j] = 0
|
||||
self.adj_mat[j][i] = 0
|
||||
|
||||
""" 打印邻接矩阵 """
|
||||
def print(self):
|
||||
""" 打印邻接矩阵 """
|
||||
print("顶点列表 =", self.vertices)
|
||||
print("邻接矩阵 =")
|
||||
print_matrix(self.adj_mat)
|
||||
@@ -964,13 +963,13 @@ comments: true
|
||||
=== "Python"
|
||||
|
||||
```python title="graph_adjacency_list.py"
|
||||
""" 基于邻接表实现的无向图类 """
|
||||
class GraphAdjList:
|
||||
""" 基于邻接表实现的无向图类 """
|
||||
# 邻接表,key: 顶点,value:该顶点的所有邻接顶点
|
||||
adj_list = {}
|
||||
|
||||
""" 构造方法 """
|
||||
def __init__(self, edges: List[List[Vertex]]) -> None:
|
||||
""" 构造方法 """
|
||||
self.adj_list = {}
|
||||
# 添加所有顶点和边
|
||||
for edge in edges:
|
||||
@@ -978,35 +977,35 @@ comments: true
|
||||
self.add_vertex(edge[1])
|
||||
self.add_edge(edge[0], edge[1])
|
||||
|
||||
""" 获取顶点数量 """
|
||||
def size(self) -> int:
|
||||
""" 获取顶点数量 """
|
||||
return len(self.adj_list)
|
||||
|
||||
""" 添加边 """
|
||||
def add_edge(self, vet1: Vertex, vet2: Vertex) -> None:
|
||||
""" 添加边 """
|
||||
if vet1 not in self.adj_list or vet2 not in self.adj_list or vet1 == vet2:
|
||||
raise ValueError
|
||||
# 添加边 vet1 - vet2
|
||||
self.adj_list[vet1].append(vet2)
|
||||
self.adj_list[vet2].append(vet1)
|
||||
|
||||
""" 删除边 """
|
||||
def remove_edge(self, vet1: Vertex, vet2: Vertex) -> None:
|
||||
""" 删除边 """
|
||||
if vet1 not in self.adj_list or vet2 not in self.adj_list or vet1 == vet2:
|
||||
raise ValueError
|
||||
# 删除边 vet1 - vet2
|
||||
self.adj_list[vet1].remove(vet2)
|
||||
self.adj_list[vet2].remove(vet1)
|
||||
|
||||
""" 添加顶点 """
|
||||
def add_vertex(self, vet: Vertex) -> None:
|
||||
""" 添加顶点 """
|
||||
if vet in self.adj_list:
|
||||
return
|
||||
# 在邻接表中添加一个新链表
|
||||
self.adj_list[vet] = []
|
||||
|
||||
""" 删除顶点 """
|
||||
def remove_vertex(self, vet: Vertex) -> None:
|
||||
""" 删除顶点 """
|
||||
if vet not in self.adj_list:
|
||||
raise ValueError
|
||||
# 在邻接表中删除顶点 vet 对应的链表
|
||||
@@ -1016,8 +1015,8 @@ comments: true
|
||||
if vet in self.adj_list[vertex]:
|
||||
self.adj_list[vertex].remove(vet)
|
||||
|
||||
""" 打印邻接表 """
|
||||
def print(self) -> None:
|
||||
""" 打印邻接表 """
|
||||
print("邻接表 =")
|
||||
for vertex in self.adj_list:
|
||||
tmp = [v.val for v in self.adj_list[vertex]]
|
||||
@@ -1223,7 +1222,7 @@ comments: true
|
||||
/* 添加边 */
|
||||
addEdge(vet1: Vertex, vet2: Vertex): void {
|
||||
if (!this.adjList.has(vet1) || !this.adjList.has(vet2) || vet1 === vet2) {
|
||||
throw new Error("Illegal Argument Exception");
|
||||
throw new Error('Illegal Argument Exception');
|
||||
}
|
||||
// 添加边 vet1 - vet2
|
||||
this.adjList.get(vet1).push(vet2);
|
||||
@@ -1233,7 +1232,7 @@ comments: true
|
||||
/* 删除边 */
|
||||
removeEdge(vet1: Vertex, vet2: Vertex): void {
|
||||
if (!this.adjList.has(vet1) || !this.adjList.has(vet2) || vet1 === vet2) {
|
||||
throw new Error("Illegal Argument Exception");
|
||||
throw new Error('Illegal Argument Exception');
|
||||
}
|
||||
// 删除边 vet1 - vet2
|
||||
this.adjList.get(vet1).splice(this.adjList.get(vet1).indexOf(vet2), 1);
|
||||
@@ -1250,7 +1249,7 @@ comments: true
|
||||
/* 删除顶点 */
|
||||
removeVertex(vet: Vertex): void {
|
||||
if (!this.adjList.has(vet)) {
|
||||
throw new Error("Illegal Argument Exception");
|
||||
throw new Error('Illegal Argument Exception');
|
||||
}
|
||||
// 在邻接表中删除顶点 vet 对应的链表
|
||||
this.adjList.delete(vet);
|
||||
@@ -1265,13 +1264,13 @@ comments: true
|
||||
|
||||
/* 打印邻接表 */
|
||||
print(): void {
|
||||
console.log("邻接表 =");
|
||||
console.log('邻接表 =');
|
||||
for (const [key, value] of this.adjList.entries()) {
|
||||
const tmp = [];
|
||||
for (const vertex of value) {
|
||||
tmp.push(vertex.val);
|
||||
}
|
||||
console.log(key.val + ": " + tmp.join());
|
||||
console.log(key.val + ': ' + tmp.join());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,9 +93,9 @@ BFS 常借助「队列」来实现。队列具有“先入先出”的性质,
|
||||
=== "Python"
|
||||
|
||||
```python title="graph_bfs.py"
|
||||
""" 广度优先遍历 BFS """
|
||||
# 使用邻接表来表示图,以便获取指定顶点的所有邻接顶点
|
||||
def graph_bfs(graph: GraphAdjList, start_vet: Vertex) -> List[Vertex]:
|
||||
""" 广度优先遍历 BFS """
|
||||
# 使用邻接表来表示图,以便获取指定顶点的所有邻接顶点
|
||||
# 顶点遍历序列
|
||||
res = []
|
||||
# 哈希表,用于记录已被访问过的顶点
|
||||
@@ -198,15 +198,15 @@ BFS 常借助「队列」来实现。队列具有“先入先出”的性质,
|
||||
const que = [startVet];
|
||||
// 以顶点 vet 为起点,循环直至访问完所有顶点
|
||||
while (que.length) {
|
||||
const vet = que.shift(); // 队首顶点出队
|
||||
res.push(vet); // 记录访问顶点
|
||||
const vet = que.shift(); // 队首顶点出队
|
||||
res.push(vet); // 记录访问顶点
|
||||
// 遍历该顶点的所有邻接顶点
|
||||
for (const adjVet of graph.adjList.get(vet) ?? []) {
|
||||
if (visited.has(adjVet)) {
|
||||
continue; // 跳过已被访问过的顶点
|
||||
continue; // 跳过已被访问过的顶点
|
||||
}
|
||||
que.push(adjVet); // 只入队未访问
|
||||
visited.add(adjVet); // 标记该顶点已被访问
|
||||
que.push(adjVet); // 只入队未访问
|
||||
visited.add(adjVet); // 标记该顶点已被访问
|
||||
}
|
||||
}
|
||||
// 返回顶点遍历序列
|
||||
@@ -378,8 +378,8 @@ BFS 常借助「队列」来实现。队列具有“先入先出”的性质,
|
||||
=== "Python"
|
||||
|
||||
```python title="graph_dfs.py"
|
||||
""" 深度优先遍历 DFS 辅助函数 """
|
||||
def dfs(graph: GraphAdjList, visited: Set[Vertex], res: List[Vertex], vet: Vertex):
|
||||
""" 深度优先遍历 DFS 辅助函数 """
|
||||
res.append(vet) # 记录访问顶点
|
||||
visited.add(vet) # 标记该顶点已被访问
|
||||
# 遍历该顶点的所有邻接顶点
|
||||
@@ -389,9 +389,8 @@ BFS 常借助「队列」来实现。队列具有“先入先出”的性质,
|
||||
# 递归访问邻接顶点
|
||||
dfs(graph, visited, res, adjVet)
|
||||
|
||||
""" 深度优先遍历 DFS """
|
||||
# 使用邻接表来表示图,以便获取指定顶点的所有邻接顶点
|
||||
def graph_dfs(graph: GraphAdjList, start_vet: Vertex) -> List[Vertex]:
|
||||
""" 深度优先遍历 DFS """
|
||||
# 顶点遍历序列
|
||||
res = []
|
||||
# 哈希表,用于记录已被访问过的顶点
|
||||
@@ -466,8 +465,8 @@ BFS 常借助「队列」来实现。队列具有“先入先出”的性质,
|
||||
```typescript title="graph_dfs.ts"
|
||||
/* 深度优先遍历 DFS 辅助函数 */
|
||||
function dfs(graph: GraphAdjList, visited: Set<Vertex>, res: Vertex[], vet: Vertex): void {
|
||||
res.push(vet); // 记录访问顶点
|
||||
visited.add(vet); // 标记该顶点已被访问
|
||||
res.push(vet); // 记录访问顶点
|
||||
visited.add(vet); // 标记该顶点已被访问
|
||||
// 遍历该顶点的所有邻接顶点
|
||||
for (const adjVet of graph.adjList.get(vet)) {
|
||||
if (visited.has(adjVet)) {
|
||||
|
||||
@@ -604,69 +604,70 @@ $$
|
||||
=== "Python"
|
||||
|
||||
```python title="array_hash_map.py"
|
||||
""" 键值对 int->String """
|
||||
class Entry:
|
||||
""" 键值对 int->String """
|
||||
def __init__(self, key, val):
|
||||
self.key = key
|
||||
self.val = val
|
||||
|
||||
""" 基于数组简易实现的哈希表 """
|
||||
class ArrayHashMap:
|
||||
""" 基于数组简易实现的哈希表 """
|
||||
def __init__(self):
|
||||
""" 构造方法 """
|
||||
# 初始化一个长度为 100 的桶(数组)
|
||||
self.bucket = [None] * 100
|
||||
|
||||
""" 哈希函数 """
|
||||
def hash_func(self, key):
|
||||
""" 哈希函数 """
|
||||
index = key % 100
|
||||
return index
|
||||
|
||||
""" 查询操作 """
|
||||
def get(self, key):
|
||||
""" 查询操作 """
|
||||
index = self.hash_func(key)
|
||||
pair = self.bucket[index]
|
||||
if pair is None:
|
||||
return None
|
||||
return pair.val
|
||||
|
||||
""" 添加操作 """
|
||||
def put(self, key, val):
|
||||
""" 添加操作 """
|
||||
pair = Entry(key, val)
|
||||
index = self.hash_func(key)
|
||||
self.bucket[index] = pair
|
||||
|
||||
""" 删除操作 """
|
||||
def remove(self, key):
|
||||
""" 删除操作 """
|
||||
index = self.hash_func(key)
|
||||
# 置为 None ,代表删除
|
||||
self.bucket[index] = None
|
||||
|
||||
""" 获取所有键值对 """
|
||||
def entry_set(self):
|
||||
""" 获取所有键值对 """
|
||||
result = []
|
||||
for pair in self.bucket:
|
||||
if pair is not None:
|
||||
result.append(pair)
|
||||
return result
|
||||
|
||||
""" 获取所有键 """
|
||||
def key_set(self):
|
||||
""" 获取所有键 """
|
||||
result = []
|
||||
for pair in self.bucket:
|
||||
if pair is not None:
|
||||
result.append(pair.key)
|
||||
return result
|
||||
|
||||
""" 获取所有值 """
|
||||
def value_set(self):
|
||||
""" 获取所有值 """
|
||||
result = []
|
||||
for pair in self.bucket:
|
||||
if pair is not None:
|
||||
result.append(pair.val)
|
||||
return result
|
||||
|
||||
""" 打印哈希表 """
|
||||
def print(self):
|
||||
""" 打印哈希表 """
|
||||
for pair in self.bucket:
|
||||
if pair is not None:
|
||||
print(pair.key, "->", pair.val)
|
||||
|
||||
@@ -47,8 +47,8 @@ comments: true
|
||||
=== "Python"
|
||||
|
||||
```python title="my_heap.py"
|
||||
""" 构造方法 """
|
||||
def __init__(self, nums: List[int]):
|
||||
""" 构造方法 """
|
||||
# 将列表元素原封不动添加进堆
|
||||
self.max_heap = nums
|
||||
# 堆化除叶结点以外的其他所有结点
|
||||
|
||||
@@ -365,16 +365,16 @@ comments: true
|
||||
=== "Python"
|
||||
|
||||
```python title="my_heap.py"
|
||||
""" 获取左子结点索引 """
|
||||
def left(self, i: int) -> int:
|
||||
""" 获取左子结点索引 """
|
||||
return 2 * i + 1
|
||||
|
||||
""" 获取右子结点索引 """
|
||||
def right(self, i: int) -> int:
|
||||
""" 获取右子结点索引 """
|
||||
return 2 * i + 2
|
||||
|
||||
""" 获取父结点索引 """
|
||||
def parent(self, i: int) -> int:
|
||||
""" 获取父结点索引 """
|
||||
return (i - 1) // 2 # 向下整除
|
||||
```
|
||||
|
||||
@@ -532,8 +532,8 @@ comments: true
|
||||
=== "Python"
|
||||
|
||||
```python title="my_heap.py"
|
||||
""" 访问堆顶元素 """
|
||||
def peek(self) -> int:
|
||||
""" 访问堆顶元素 """
|
||||
return self.max_heap[0]
|
||||
```
|
||||
|
||||
@@ -681,15 +681,15 @@ comments: true
|
||||
=== "Python"
|
||||
|
||||
```python title="my_heap.py"
|
||||
""" 元素入堆 """
|
||||
def push(self, val: int):
|
||||
""" 元素入堆 """
|
||||
# 添加结点
|
||||
self.max_heap.append(val)
|
||||
# 从底至顶堆化
|
||||
self.sift_up(self.size() - 1)
|
||||
|
||||
""" 从结点 i 开始,从底至顶堆化 """
|
||||
def sift_up(self, i: int):
|
||||
""" 从结点 i 开始,从底至顶堆化 """
|
||||
while True:
|
||||
# 获取结点 i 的父结点
|
||||
p = self.parent(i)
|
||||
@@ -995,8 +995,8 @@ comments: true
|
||||
=== "Python"
|
||||
|
||||
```python title="my_heap.py"
|
||||
""" 元素出堆 """
|
||||
def poll(self) -> int:
|
||||
""" 元素出堆 """
|
||||
# 判空处理
|
||||
assert not self.is_empty()
|
||||
# 交换根结点与最右叶结点(即交换首元素与尾元素)
|
||||
@@ -1008,8 +1008,8 @@ comments: true
|
||||
# 返回堆顶元素
|
||||
return val
|
||||
|
||||
""" 从结点 i 开始,从顶至底堆化 """
|
||||
def sift_down(self, i: int):
|
||||
""" 从结点 i 开始,从顶至底堆化 """
|
||||
while True:
|
||||
# 判断结点 i, l, r 中值最大的结点,记为 ma
|
||||
l, r, ma = self.left(i), self.right(i), i
|
||||
@@ -1113,7 +1113,7 @@ comments: true
|
||||
/* 元素出堆 */
|
||||
poll(): number {
|
||||
// 判空处理
|
||||
if (this.isEmpty()) throw new RangeError("Heap is empty.");
|
||||
if (this.isEmpty()) throw new RangeError('Heap is empty.');
|
||||
// 交换根结点与最右叶结点(即交换首元素与尾元素)
|
||||
this.swap(0, this.size() - 1);
|
||||
// 删除结点
|
||||
@@ -1128,7 +1128,8 @@ comments: true
|
||||
siftDown(i: number): void {
|
||||
while (true) {
|
||||
// 判断结点 i, l, r 中值最大的结点,记为 ma
|
||||
const l = this.left(i), r = this.right(i);
|
||||
const l = this.left(i),
|
||||
r = this.right(i);
|
||||
let ma = i;
|
||||
if (l < this.size() && this.maxHeap[l] > this.maxHeap[ma]) ma = l;
|
||||
if (r < this.size() && this.maxHeap[r] > this.maxHeap[ma]) ma = r;
|
||||
|
||||
@@ -98,8 +98,8 @@ $$
|
||||
=== "Python"
|
||||
|
||||
```python title="binary_search.py"
|
||||
""" 二分查找(双闭区间) """
|
||||
def binary_search(nums, target):
|
||||
""" 二分查找(双闭区间) """
|
||||
# 初始化双闭区间 [0, n-1] ,即 i, j 分别指向数组首元素、尾元素
|
||||
i, j = 0, len(nums) - 1
|
||||
while i <= j:
|
||||
@@ -145,7 +145,7 @@ $$
|
||||
let i = 0, j = nums.length - 1;
|
||||
// 循环,当搜索区间为空时跳出(当 i > j 时为空)
|
||||
while (i <= j) {
|
||||
let m = parseInt((i + j) / 2); // 计算中点索引 m ,在 JS 中需使用 parseInt 函数取整
|
||||
const m = parseInt((i + j) / 2); // 计算中点索引 m ,在 JS 中需使用 parseInt 函数取整
|
||||
if (nums[m] < target) // 此情况说明 target 在区间 [m+1, j] 中
|
||||
i = m + 1;
|
||||
else if (nums[m] > target) // 此情况说明 target 在区间 [i, m-1] 中
|
||||
@@ -167,7 +167,7 @@ $$
|
||||
let i = 0, j = nums.length - 1;
|
||||
// 循环,当搜索区间为空时跳出(当 i > j 时为空)
|
||||
while (i <= j) {
|
||||
const m = Math.floor(i + (j - i) / 2); // 计算中点索引 m
|
||||
const m = Math.floor((i + j) / 2); // 计算中点索引 m
|
||||
if (nums[m] < target) { // 此情况说明 target 在区间 [m+1, j] 中
|
||||
i = m + 1;
|
||||
} else if (nums[m] > target) { // 此情况说明 target 在区间 [i, m-1] 中
|
||||
@@ -309,8 +309,8 @@ $$
|
||||
=== "Python"
|
||||
|
||||
```python title="binary_search.py"
|
||||
""" 二分查找(左闭右开) """
|
||||
def binary_search1(nums, target):
|
||||
""" 二分查找(左闭右开) """
|
||||
# 初始化左闭右开 [0, n) ,即 i, j 分别指向数组首元素、尾元素+1
|
||||
i, j = 0, len(nums)
|
||||
# 循环,当搜索区间为空时跳出(当 i = j 时为空)
|
||||
@@ -357,7 +357,7 @@ $$
|
||||
let i = 0, j = nums.length;
|
||||
// 循环,当搜索区间为空时跳出(当 i = j 时为空)
|
||||
while (i < j) {
|
||||
let m = parseInt((i + j) / 2); // 计算中点索引 m ,在 JS 中需使用 parseInt 函数取整
|
||||
const m = parseInt((i + j) / 2); // 计算中点索引 m ,在 JS 中需使用 parseInt 函数取整
|
||||
if (nums[m] < target) // 此情况说明 target 在区间 [m+1, j) 中
|
||||
i = m + 1;
|
||||
else if (nums[m] > target) // 此情况说明 target 在区间 [i, m) 中
|
||||
@@ -379,7 +379,7 @@ $$
|
||||
let i = 0, j = nums.length;
|
||||
// 循环,当搜索区间为空时跳出(当 i = j 时为空)
|
||||
while (i < j) {
|
||||
const m = Math.floor(i + (j - i) / 2); // 计算中点索引 m
|
||||
const m = Math.floor((i + j) / 2); // 计算中点索引 m
|
||||
if (nums[m] < target) { // 此情况说明 target 在区间 [m+1, j) 中
|
||||
i = m + 1;
|
||||
} else if (nums[m] > target) { // 此情况说明 target 在区间 [i, m) 中
|
||||
|
||||
@@ -45,8 +45,8 @@ comments: true
|
||||
=== "Python"
|
||||
|
||||
```python title="hashing_search.py"
|
||||
""" 哈希查找(数组) """
|
||||
def hashing_search_array(mapp, target):
|
||||
""" 哈希查找(数组) """
|
||||
# 哈希表的 key: 目标元素,value: 索引
|
||||
# 若哈希表中无此 key ,返回 -1
|
||||
return mapp.get(target, -1)
|
||||
@@ -85,7 +85,7 @@ comments: true
|
||||
function hashingSearchArray(map: Map<number, number>, target: number): number {
|
||||
// 哈希表的 key: 目标元素,value: 索引
|
||||
// 若哈希表中无此 key ,返回 -1
|
||||
return map.has(target) ? map.get(target) as number : -1;
|
||||
return map.has(target) ? (map.get(target) as number) : -1;
|
||||
}
|
||||
```
|
||||
|
||||
@@ -163,8 +163,8 @@ comments: true
|
||||
=== "Python"
|
||||
|
||||
```python title="hashing_search.py"
|
||||
""" 哈希查找(链表) """
|
||||
def hashing_search_linkedlist(mapp, target):
|
||||
""" 哈希查找(链表) """
|
||||
# 哈希表的 key: 目标元素,value: 结点对象
|
||||
# 若哈希表中无此 key ,返回 -1
|
||||
return mapp.get(target, -1)
|
||||
@@ -203,7 +203,7 @@ comments: true
|
||||
function hashingSearchLinkedList(map: Map<number, ListNode>, target: number): ListNode | null {
|
||||
// 哈希表的 key: 目标结点值,value: 结点对象
|
||||
// 若哈希表中无此 key ,返回 null
|
||||
return map.has(target) ? map.get(target) as ListNode : null;
|
||||
return map.has(target) ? (map.get(target) as ListNode) : null;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -49,8 +49,8 @@ comments: true
|
||||
=== "Python"
|
||||
|
||||
```python title="linear_search.py"
|
||||
""" 线性查找(数组) """
|
||||
def linear_search_array(nums, target):
|
||||
""" 线性查找(数组) """
|
||||
# 遍历数组
|
||||
for i in range(len(nums)):
|
||||
if nums[i] == target: # 找到目标元素,返回其索引
|
||||
@@ -206,8 +206,8 @@ comments: true
|
||||
=== "Python"
|
||||
|
||||
```python title="linear_search.py"
|
||||
""" 线性查找(链表) """
|
||||
def linear_search_linkedlist(head, target):
|
||||
""" 线性查找(链表) """
|
||||
# 遍历链表
|
||||
while head:
|
||||
if head.val == target: # 找到目标结点,返回之
|
||||
|
||||
@@ -87,8 +87,8 @@ comments: true
|
||||
=== "Python"
|
||||
|
||||
```python title="bubble_sort.py"
|
||||
""" 冒泡排序 """
|
||||
def bubble_sort(nums):
|
||||
""" 冒泡排序 """
|
||||
n = len(nums)
|
||||
# 外循环:待排序元素数量为 n-1, n-2, ..., 1
|
||||
for i in range(n - 1, 0, -1):
|
||||
@@ -295,8 +295,8 @@ comments: true
|
||||
=== "Python"
|
||||
|
||||
```python title="bubble_sort.py"
|
||||
""" 冒泡排序(标志优化) """
|
||||
def bubble_sort_with_flag(nums):
|
||||
""" 冒泡排序(标志优化) """
|
||||
n = len(nums)
|
||||
# 外循环:待排序元素数量为 n-1, n-2, ..., 1
|
||||
for i in range(n - 1, 0, -1):
|
||||
|
||||
@@ -63,9 +63,9 @@ comments: true
|
||||
=== "Python"
|
||||
|
||||
```python title="insertion_sort.py"
|
||||
""" 插入排序 """
|
||||
def insertion_sort(nums):
|
||||
# 外循环:base = nums[1], nums[2], ..., nums[n-1]
|
||||
""" 插入排序 """
|
||||
# 外循环:base = nums[1], nums[2], ..., nums[n-1]
|
||||
for i in range(1, len(nums)):
|
||||
base = nums[i]
|
||||
j = i - 1
|
||||
|
||||
@@ -146,10 +146,10 @@ comments: true
|
||||
=== "Python"
|
||||
|
||||
```python title="merge_sort.py"
|
||||
""" 合并左子数组和右子数组 """
|
||||
# 左子数组区间 [left, mid]
|
||||
# 右子数组区间 [mid + 1, right]
|
||||
def merge(nums, left, mid, right):
|
||||
""" 合并左子数组和右子数组 """
|
||||
# 左子数组区间 [left, mid]
|
||||
# 右子数组区间 [mid + 1, right]
|
||||
# 初始化辅助数组 借助 copy模块
|
||||
tmp = nums[left:right + 1]
|
||||
# 左子数组的起始索引和结束索引
|
||||
@@ -173,8 +173,8 @@ comments: true
|
||||
nums[k] = tmp[j]
|
||||
j += 1
|
||||
|
||||
""" 归并排序 """
|
||||
def merge_sort(nums, left, right):
|
||||
""" 归并排序 """
|
||||
# 终止条件
|
||||
if left >= right:
|
||||
return # 当子数组长度为 1 时终止递归
|
||||
|
||||
@@ -100,8 +100,8 @@ comments: true
|
||||
=== "Python"
|
||||
|
||||
```python title="quick_sort.py"
|
||||
""" 哨兵划分 """
|
||||
def partition(self, nums, left, right):
|
||||
""" 哨兵划分 """
|
||||
# 以 nums[left] 作为基准数
|
||||
i, j = left, right
|
||||
while i < j:
|
||||
@@ -333,8 +333,8 @@ comments: true
|
||||
=== "Python"
|
||||
|
||||
```python title="quick_sort.py"
|
||||
""" 快速排序 """
|
||||
def quick_sort(self, nums, left, right):
|
||||
""" 快速排序 """
|
||||
# 子数组长度为 1 时终止递归
|
||||
if left >= right:
|
||||
return
|
||||
@@ -552,8 +552,8 @@ comments: true
|
||||
=== "Python"
|
||||
|
||||
```python title="quick_sort.py"
|
||||
""" 选取三个元素的中位数 """
|
||||
def median_three(self, nums, left, mid, right):
|
||||
""" 选取三个元素的中位数 """
|
||||
# 此处使用异或运算来简化代码
|
||||
# 异或规则为 0 ^ 0 = 1 ^ 1 = 0, 0 ^ 1 = 1 ^ 0 = 1
|
||||
if (nums[left] < nums[mid]) ^ (nums[left] < nums[right]):
|
||||
@@ -562,8 +562,8 @@ comments: true
|
||||
return mid
|
||||
return right
|
||||
|
||||
""" 哨兵划分(三数取中值) """
|
||||
def partition(self, nums, left, right):
|
||||
""" 哨兵划分(三数取中值) """
|
||||
# 以 nums[left] 作为基准数
|
||||
med = self.median_three(nums, left, (left + right) // 2, right)
|
||||
# 将中位数交换至数组最左端
|
||||
@@ -845,8 +845,8 @@ comments: true
|
||||
=== "Python"
|
||||
|
||||
```python title="quick_sort.py"
|
||||
""" 快速排序(尾递归优化) """
|
||||
def quick_sort(self, nums, left, right):
|
||||
""" 快速排序(尾递归优化) """
|
||||
# 子数组长度为 1 时终止
|
||||
while left < right:
|
||||
# 哨兵划分操作
|
||||
|
||||
@@ -590,30 +590,31 @@ comments: true
|
||||
=== "Python"
|
||||
|
||||
```python title="linkedlist_deque.py"
|
||||
""" 双向链表结点 """
|
||||
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():
|
||||
@@ -632,16 +633,16 @@ comments: true
|
||||
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
|
||||
@@ -666,24 +667,24 @@ comments: true
|
||||
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()):
|
||||
@@ -790,106 +791,106 @@ comments: true
|
||||
|
||||
/* 基于双向链表实现的双向队列 */
|
||||
class LinkedListDeque {
|
||||
front; // 头结点 front
|
||||
rear; // 尾结点 rear
|
||||
len; // 双向队列的长度
|
||||
#front; // 头结点 front
|
||||
#rear; // 尾结点 rear
|
||||
#queSize; // 双向队列的长度
|
||||
|
||||
constructor() {
|
||||
this.front = null;
|
||||
this.rear = null;
|
||||
this.len = 0;
|
||||
this.#front = null;
|
||||
this.#rear = null;
|
||||
this.#queSize = 0;
|
||||
}
|
||||
|
||||
/* 队尾入队操作 */
|
||||
pushLast(val) {
|
||||
const node = new ListNode(val);
|
||||
// 若链表为空,则令 front, rear 都指向 node
|
||||
if (this.len === 0) {
|
||||
this.front = node;
|
||||
this.rear = node;
|
||||
if (this.#queSize === 0) {
|
||||
this.#front = node;
|
||||
this.#rear = node;
|
||||
} else {
|
||||
// 将 node 添加至链表尾部
|
||||
this.rear.next = node;
|
||||
node.prev = this.rear;
|
||||
this.rear = node; // 更新尾结点
|
||||
this.#rear.next = node;
|
||||
node.prev = this.#rear;
|
||||
this.#rear = node; // 更新尾结点
|
||||
}
|
||||
this.len++;
|
||||
this.#queSize++;
|
||||
}
|
||||
|
||||
/* 队首入队操作 */
|
||||
pushFirst(val) {
|
||||
const node = new ListNode(val);
|
||||
// 若链表为空,则令 front, rear 都指向 node
|
||||
if (this.len === 0) {
|
||||
this.front = node;
|
||||
this.rear = node;
|
||||
if (this.#queSize === 0) {
|
||||
this.#front = node;
|
||||
this.#rear = node;
|
||||
} else {
|
||||
// 将 node 添加至链表头部
|
||||
this.front.prev = node;
|
||||
node.next = this.front;
|
||||
this.front = node; // 更新头结点
|
||||
this.#front.prev = node;
|
||||
node.next = this.#front;
|
||||
this.#front = node; // 更新头结点
|
||||
}
|
||||
this.len++;
|
||||
this.#queSize++;
|
||||
}
|
||||
|
||||
/* 队尾出队操作 */
|
||||
pollLast() {
|
||||
if (this.len === 0) {
|
||||
if (this.#queSize === 0) {
|
||||
return null;
|
||||
}
|
||||
const value = this.rear.val; // 存储尾结点值
|
||||
const value = this.#rear.val; // 存储尾结点值
|
||||
// 删除尾结点
|
||||
let temp = this.rear.prev;
|
||||
let temp = this.#rear.prev;
|
||||
if (temp !== null) {
|
||||
temp.next = null;
|
||||
this.rear.prev = null;
|
||||
this.#rear.prev = null;
|
||||
}
|
||||
this.rear = temp; // 更新尾结点
|
||||
this.len--;
|
||||
this.#rear = temp; // 更新尾结点
|
||||
this.#queSize--;
|
||||
return value;
|
||||
}
|
||||
|
||||
/* 队首出队操作 */
|
||||
pollFirst() {
|
||||
if (this.len === 0) {
|
||||
if (this.#queSize === 0) {
|
||||
return null;
|
||||
}
|
||||
const value = this.front.val; // 存储尾结点值
|
||||
const value = this.#front.val; // 存储尾结点值
|
||||
// 删除头结点
|
||||
let temp = this.front.next;
|
||||
let temp = this.#front.next;
|
||||
if (temp !== null) {
|
||||
temp.prev = null;
|
||||
this.front.next = null;
|
||||
this.#front.next = null;
|
||||
}
|
||||
this.front = temp; // 更新头结点
|
||||
this.len--;
|
||||
this.#front = temp; // 更新头结点
|
||||
this.#queSize--;
|
||||
return value;
|
||||
}
|
||||
|
||||
/* 访问队尾元素 */
|
||||
peekLast() {
|
||||
return this.len === 0 ? null : this.rear.val;
|
||||
return this.#queSize === 0 ? null : this.#rear.val;
|
||||
}
|
||||
|
||||
/* 访问队首元素 */
|
||||
peekFirst() {
|
||||
return this.len === 0 ? null : this.front.val;
|
||||
return this.#queSize === 0 ? null : this.#front.val;
|
||||
}
|
||||
|
||||
/* 获取双向队列的长度 */
|
||||
size() {
|
||||
return this.len;
|
||||
return this.#queSize;
|
||||
}
|
||||
|
||||
/* 判断双向队列是否为空 */
|
||||
isEmpty() {
|
||||
return this.len === 0;
|
||||
return this.#queSize === 0;
|
||||
}
|
||||
|
||||
/* 打印双向队列 */
|
||||
print() {
|
||||
const arr = [];
|
||||
let temp = this.front;
|
||||
let temp = this.#front;
|
||||
while (temp !== null) {
|
||||
arr.push(temp.val);
|
||||
temp = temp.next;
|
||||
@@ -917,21 +918,21 @@ comments: true
|
||||
|
||||
/* 基于双向链表实现的双向队列 */
|
||||
class LinkedListDeque {
|
||||
front: ListNode; // 头结点 front
|
||||
rear: ListNode; // 尾结点 rear
|
||||
len: number; // 双向队列的长度
|
||||
private front: ListNode; // 头结点 front
|
||||
private rear: ListNode; // 尾结点 rear
|
||||
private queSize: number; // 双向队列的长度
|
||||
|
||||
constructor() {
|
||||
this.front = null;
|
||||
this.rear = null;
|
||||
this.len = 0;
|
||||
this.queSize = 0;
|
||||
}
|
||||
|
||||
/* 队尾入队操作 */
|
||||
pushLast(val: number): void {
|
||||
const node: ListNode = new ListNode(val);
|
||||
// 若链表为空,则令 front, rear 都指向 node
|
||||
if (this.len === 0) {
|
||||
if (this.queSize === 0) {
|
||||
this.front = node;
|
||||
this.rear = node;
|
||||
} else {
|
||||
@@ -940,14 +941,14 @@ comments: true
|
||||
node.prev = this.rear;
|
||||
this.rear = node; // 更新尾结点
|
||||
}
|
||||
this.len++;
|
||||
this.queSize++;
|
||||
}
|
||||
|
||||
/* 队首入队操作 */
|
||||
pushFirst(val: number): void {
|
||||
const node: ListNode = new ListNode(val);
|
||||
// 若链表为空,则令 front, rear 都指向 node
|
||||
if (this.len === 0) {
|
||||
if (this.queSize === 0) {
|
||||
this.front = node;
|
||||
this.rear = node;
|
||||
} else {
|
||||
@@ -956,12 +957,12 @@ comments: true
|
||||
node.next = this.front;
|
||||
this.front = node; // 更新头结点
|
||||
}
|
||||
this.len++;
|
||||
this.queSize++;
|
||||
}
|
||||
|
||||
/* 队尾出队操作 */
|
||||
pollLast(): number {
|
||||
if (this.len === 0) {
|
||||
if (this.queSize === 0) {
|
||||
return null;
|
||||
}
|
||||
const value: number = this.rear.val; // 存储尾结点值
|
||||
@@ -972,13 +973,13 @@ comments: true
|
||||
this.rear.prev = null;
|
||||
}
|
||||
this.rear = temp; // 更新尾结点
|
||||
this.len--;
|
||||
this.queSize--;
|
||||
return value;
|
||||
}
|
||||
|
||||
/* 队首出队操作 */
|
||||
pollFirst(): number {
|
||||
if (this.len === 0) {
|
||||
if (this.queSize === 0) {
|
||||
return null;
|
||||
}
|
||||
const value: number = this.front.val; // 存储尾结点值
|
||||
@@ -989,28 +990,28 @@ comments: true
|
||||
this.front.next = null;
|
||||
}
|
||||
this.front = temp; // 更新头结点
|
||||
this.len--;
|
||||
this.queSize--;
|
||||
return value;
|
||||
}
|
||||
|
||||
/* 访问队尾元素 */
|
||||
peekLast(): number {
|
||||
return this.len === 0 ? null : this.rear.val;
|
||||
return this.queSize === 0 ? null : this.rear.val;
|
||||
}
|
||||
|
||||
/* 访问队首元素 */
|
||||
peekFirst(): number {
|
||||
return this.len === 0 ? null : this.front.val;
|
||||
return this.queSize === 0 ? null : this.front.val;
|
||||
}
|
||||
|
||||
/* 获取双向队列的长度 */
|
||||
size(): number {
|
||||
return this.len;
|
||||
return this.queSize;
|
||||
}
|
||||
|
||||
/* 判断双向队列是否为空 */
|
||||
isEmpty(): boolean {
|
||||
return this.len === 0;
|
||||
return this.queSize === 0;
|
||||
}
|
||||
|
||||
/* 打印双向队列 */
|
||||
@@ -1593,35 +1594,35 @@ comments: true
|
||||
=== "Python"
|
||||
|
||||
```python title="array_deque.py"
|
||||
""" 基于环形数组实现的双向队列 """
|
||||
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
|
||||
@@ -1632,8 +1633,8 @@ comments: true
|
||||
self.nums[self.front] = num
|
||||
self.que_size += 1
|
||||
|
||||
""" 队尾入队 """
|
||||
def push_last(self, num):
|
||||
""" 队尾入队 """
|
||||
if self.que_size == self.capacity():
|
||||
print("双向队列已满")
|
||||
return
|
||||
@@ -1643,34 +1644,34 @@ comments: true
|
||||
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):
|
||||
|
||||
@@ -429,23 +429,24 @@ comments: true
|
||||
=== "Python"
|
||||
|
||||
```python title="linkedlist_queue.py"
|
||||
""" 基于链表实现的队列 """
|
||||
class LinkedListQueue:
|
||||
""" 基于链表实现的队列 """
|
||||
def __init__(self):
|
||||
""" 构造方法 """
|
||||
self.__front = None # 头结点 front
|
||||
self.__rear = None # 尾结点 rear
|
||||
self.__size = 0
|
||||
|
||||
""" 获取队列的长度 """
|
||||
def size(self):
|
||||
""" 获取队列的长度 """
|
||||
return self.__size
|
||||
|
||||
""" 判断队列是否为空 """
|
||||
def is_empty(self):
|
||||
""" 判断队列是否为空 """
|
||||
return not self.__front
|
||||
|
||||
""" 入队 """
|
||||
def push(self, num):
|
||||
""" 入队 """
|
||||
# 尾结点后添加 num
|
||||
node = ListNode(num)
|
||||
# 如果队列为空,则令头、尾结点都指向该结点
|
||||
@@ -458,23 +459,23 @@ comments: true
|
||||
self.__rear = node
|
||||
self.__size += 1
|
||||
|
||||
""" 出队 """
|
||||
def poll(self):
|
||||
""" 出队 """
|
||||
num = self.peek()
|
||||
# 删除头结点
|
||||
self.__front = self.__front.next
|
||||
self.__size -= 1
|
||||
return num
|
||||
|
||||
""" 访问队首元素 """
|
||||
def peek(self):
|
||||
""" 访问队首元素 """
|
||||
if self.size() == 0:
|
||||
print("队列为空")
|
||||
return False
|
||||
return self.__front.val
|
||||
|
||||
""" 转化为列表用于打印 """
|
||||
def to_list(self):
|
||||
""" 转化为列表用于打印 """
|
||||
queue = []
|
||||
temp = self.__front
|
||||
while temp:
|
||||
@@ -614,7 +615,7 @@ comments: true
|
||||
/* 基于链表实现的队列 */
|
||||
class LinkedListQueue {
|
||||
private front: ListNode | null; // 头结点 front
|
||||
private rear: ListNode | null; // 尾结点 rear
|
||||
private rear: ListNode | null; // 尾结点 rear
|
||||
private queSize: number = 0;
|
||||
|
||||
constructor() {
|
||||
@@ -651,8 +652,7 @@ comments: true
|
||||
/* 出队 */
|
||||
poll(): number {
|
||||
const num = this.peek();
|
||||
if (!this.front)
|
||||
throw new Error("队列为空")
|
||||
if (!this.front) throw new Error('队列为空');
|
||||
// 删除头结点
|
||||
this.front = this.front.next;
|
||||
this.queSize--;
|
||||
@@ -661,8 +661,7 @@ comments: true
|
||||
|
||||
/* 访问队首元素 */
|
||||
peek(): number {
|
||||
if (this.size === 0)
|
||||
throw new Error("队列为空");
|
||||
if (this.size === 0) throw new Error('队列为空');
|
||||
return this.front!.val;
|
||||
}
|
||||
|
||||
@@ -1105,27 +1104,28 @@ comments: true
|
||||
=== "Python"
|
||||
|
||||
```python title="array_queue.py"
|
||||
""" 基于环形数组实现的队列 """
|
||||
class ArrayQueue:
|
||||
""" 基于环形数组实现的队列 """
|
||||
def __init__(self, size):
|
||||
""" 构造方法 """
|
||||
self.__nums = [0] * size # 用于存储队列元素的数组
|
||||
self.__front = 0 # 队首指针,指向队首元素
|
||||
self.__size = 0 # 队列长度
|
||||
|
||||
""" 获取队列的容量 """
|
||||
def capacity(self):
|
||||
""" 获取队列的容量 """
|
||||
return len(self.__nums)
|
||||
|
||||
""" 获取队列的长度 """
|
||||
def size(self):
|
||||
""" 获取队列的长度 """
|
||||
return self.__size
|
||||
|
||||
""" 判断队列是否为空 """
|
||||
def is_empty(self):
|
||||
""" 判断队列是否为空 """
|
||||
return self.__size == 0
|
||||
|
||||
""" 入队 """
|
||||
def push(self, num):
|
||||
""" 入队 """
|
||||
assert self.__size < self.capacity(), "队列已满"
|
||||
# 计算尾指针,指向队尾索引 + 1
|
||||
# 通过取余操作,实现 rear 越过数组尾部后回到头部
|
||||
@@ -1134,21 +1134,21 @@ comments: true
|
||||
self.__nums[rear] = num
|
||||
self.__size += 1
|
||||
|
||||
""" 出队 """
|
||||
def poll(self):
|
||||
""" 出队 """
|
||||
num = self.peek()
|
||||
# 队首指针向后移动一位,若越过尾部则返回到数组头部
|
||||
self.__front = (self.__front + 1) % self.capacity()
|
||||
self.__size -= 1
|
||||
return num
|
||||
|
||||
""" 访问队首元素 """
|
||||
def peek(self):
|
||||
""" 访问队首元素 """
|
||||
assert not self.is_empty(), "队列为空"
|
||||
return self.__nums[self.__front]
|
||||
|
||||
""" 返回列表用于打印 """
|
||||
def to_list(self):
|
||||
""" 返回列表用于打印 """
|
||||
res = [0] * self.size()
|
||||
j = self.__front
|
||||
for i in range(self.size()):
|
||||
|
||||
@@ -410,42 +410,43 @@ comments: true
|
||||
=== "Python"
|
||||
|
||||
```python title="linkedlist_stack.py"
|
||||
""" 基于链表实现的栈 """
|
||||
class LinkedListStack:
|
||||
""" 基于链表实现的栈 """
|
||||
def __init__(self):
|
||||
""" 构造方法 """
|
||||
self.__peek = None
|
||||
self.__size = 0
|
||||
|
||||
""" 获取栈的长度 """
|
||||
def size(self):
|
||||
""" 获取栈的长度 """
|
||||
return self.__size
|
||||
|
||||
""" 判断栈是否为空 """
|
||||
def is_empty(self):
|
||||
""" 判断栈是否为空 """
|
||||
return not self.__peek
|
||||
|
||||
""" 入栈 """
|
||||
def push(self, val):
|
||||
""" 入栈 """
|
||||
node = ListNode(val)
|
||||
node.next = self.__peek
|
||||
self.__peek = node
|
||||
self.__size += 1
|
||||
|
||||
""" 出栈 """
|
||||
def pop(self):
|
||||
""" 出栈 """
|
||||
num = self.peek()
|
||||
self.__peek = self.__peek.next
|
||||
self.__size -= 1
|
||||
return num
|
||||
|
||||
""" 访问栈顶元素 """
|
||||
def peek(self):
|
||||
""" 访问栈顶元素 """
|
||||
# 判空处理
|
||||
if not self.__peek: return None
|
||||
return self.__peek.val
|
||||
|
||||
""" 转化为列表用于打印 """
|
||||
def to_list(self):
|
||||
""" 转化为列表用于打印 """
|
||||
arr = []
|
||||
node = self.__peek
|
||||
while node:
|
||||
@@ -574,8 +575,8 @@ comments: true
|
||||
```typescript title="linkedlist_stack.ts"
|
||||
/* 基于链表实现的栈 */
|
||||
class LinkedListStack {
|
||||
private stackPeek: ListNode | null; // 将头结点作为栈顶
|
||||
private stkSize: number = 0; // 栈的长度
|
||||
private stackPeek: ListNode | null; // 将头结点作为栈顶
|
||||
private stkSize: number = 0; // 栈的长度
|
||||
|
||||
constructor() {
|
||||
this.stackPeek = null;
|
||||
@@ -602,8 +603,7 @@ comments: true
|
||||
/* 出栈 */
|
||||
pop(): number {
|
||||
const num = this.peek();
|
||||
if (!this.stackPeek)
|
||||
throw new Error("栈为空");
|
||||
if (!this.stackPeek) throw new Error('栈为空');
|
||||
this.stackPeek = this.stackPeek.next;
|
||||
this.stkSize--;
|
||||
return num;
|
||||
@@ -611,8 +611,7 @@ comments: true
|
||||
|
||||
/* 访问栈顶元素 */
|
||||
peek(): number {
|
||||
if (!this.stackPeek)
|
||||
throw new Error("栈为空");
|
||||
if (!this.stackPeek) throw new Error('栈为空');
|
||||
return this.stackPeek.val;
|
||||
}
|
||||
|
||||
@@ -953,35 +952,36 @@ comments: true
|
||||
=== "Python"
|
||||
|
||||
```python title="array_stack.py"
|
||||
""" 基于数组实现的栈 """
|
||||
class ArrayStack:
|
||||
""" 基于数组实现的栈 """
|
||||
def __init__(self):
|
||||
""" 构造方法 """
|
||||
self.__stack = []
|
||||
|
||||
""" 获取栈的长度 """
|
||||
def size(self):
|
||||
""" 获取栈的长度 """
|
||||
return len(self.__stack)
|
||||
|
||||
""" 判断栈是否为空 """
|
||||
def is_empty(self):
|
||||
""" 判断栈是否为空 """
|
||||
return self.__stack == []
|
||||
|
||||
""" 入栈 """
|
||||
def push(self, item):
|
||||
""" 入栈 """
|
||||
self.__stack.append(item)
|
||||
|
||||
""" 出栈 """
|
||||
def pop(self):
|
||||
""" 出栈 """
|
||||
assert not self.is_empty(), "栈为空"
|
||||
return self.__stack.pop()
|
||||
|
||||
""" 访问栈顶元素 """
|
||||
def peek(self):
|
||||
""" 访问栈顶元素 """
|
||||
assert not self.is_empty(), "栈为空"
|
||||
return self.__stack[-1]
|
||||
|
||||
""" 返回列表用于打印 """
|
||||
def to_list(self):
|
||||
""" 返回列表用于打印 """
|
||||
return self.__stack
|
||||
```
|
||||
|
||||
@@ -1044,43 +1044,43 @@ comments: true
|
||||
```javascript title="array_stack.js"
|
||||
/* 基于数组实现的栈 */
|
||||
class ArrayStack {
|
||||
stack;
|
||||
#stack;
|
||||
constructor() {
|
||||
this.stack = [];
|
||||
this.#stack = [];
|
||||
}
|
||||
|
||||
/* 获取栈的长度 */
|
||||
get size() {
|
||||
return this.stack.length;
|
||||
return this.#stack.length;
|
||||
}
|
||||
|
||||
/* 判断栈是否为空 */
|
||||
empty() {
|
||||
return this.stack.length === 0;
|
||||
return this.#stack.length === 0;
|
||||
}
|
||||
|
||||
/* 入栈 */
|
||||
push(num) {
|
||||
this.stack.push(num);
|
||||
this.#stack.push(num);
|
||||
}
|
||||
|
||||
/* 出栈 */
|
||||
pop() {
|
||||
if (this.empty())
|
||||
throw new Error("栈为空");
|
||||
return this.stack.pop();
|
||||
return this.#stack.pop();
|
||||
}
|
||||
|
||||
/* 访问栈顶元素 */
|
||||
top() {
|
||||
if (this.empty())
|
||||
throw new Error("栈为空");
|
||||
return this.stack[this.stack.length - 1];
|
||||
return this.#stack[this.#stack.length - 1];
|
||||
}
|
||||
|
||||
/* 返回 Array */
|
||||
toArray() {
|
||||
return this.stack;
|
||||
return this.#stack;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
@@ -194,15 +194,15 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit
|
||||
=== "Python"
|
||||
|
||||
```python title="avl_tree.py"
|
||||
""" 获取结点高度 """
|
||||
def height(self, node: Optional[TreeNode]) -> int:
|
||||
""" 获取结点高度 """
|
||||
# 空结点高度为 -1 ,叶结点高度为 0
|
||||
if node is not None:
|
||||
return node.height
|
||||
return -1
|
||||
|
||||
""" 更新结点高度 """
|
||||
def __update_height(self, node: Optional[TreeNode]):
|
||||
""" 更新结点高度 """
|
||||
# 结点高度等于最高子树高度 + 1
|
||||
node.height = max([self.height(node.left), self.height(node.right)]) + 1
|
||||
```
|
||||
@@ -242,7 +242,7 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit
|
||||
}
|
||||
|
||||
/* 更新结点高度 */
|
||||
updateHeight(node) {
|
||||
#updateHeight(node) {
|
||||
// 结点高度等于最高子树高度 + 1
|
||||
node.height = Math.max(this.height(node.left), this.height(node.right)) + 1;
|
||||
}
|
||||
@@ -354,8 +354,8 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit
|
||||
=== "Python"
|
||||
|
||||
```python title="avl_tree.py"
|
||||
""" 获取平衡因子 """
|
||||
def balance_factor(self, node: Optional[TreeNode]) -> int:
|
||||
""" 获取平衡因子 """
|
||||
# 空结点平衡因子为 0
|
||||
if node is None:
|
||||
return 0
|
||||
@@ -517,8 +517,8 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影
|
||||
=== "Python"
|
||||
|
||||
```python title="avl_tree.py"
|
||||
""" 右旋操作 """
|
||||
def __right_rotate(self, node: Optional[TreeNode]) -> TreeNode:
|
||||
""" 右旋操作 """
|
||||
child = node.left
|
||||
grand_child = child.right
|
||||
# 以 child 为原点,将 node 向右旋转
|
||||
@@ -553,15 +553,15 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影
|
||||
|
||||
```javascript title="avl_tree.js"
|
||||
/* 右旋操作 */
|
||||
rightRotate(node) {
|
||||
#rightRotate(node) {
|
||||
const child = node.left;
|
||||
const grandChild = child.right;
|
||||
// 以 child 为原点,将 node 向右旋转
|
||||
child.right = node;
|
||||
node.left = grandChild;
|
||||
// 更新结点高度
|
||||
this.updateHeight(node);
|
||||
this.updateHeight(child);
|
||||
this.#updateHeight(node);
|
||||
this.#updateHeight(child);
|
||||
// 返回旋转后子树的根结点
|
||||
return child;
|
||||
}
|
||||
@@ -701,8 +701,8 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影
|
||||
=== "Python"
|
||||
|
||||
```python title="avl_tree.py"
|
||||
""" 左旋操作 """
|
||||
def __left_rotate(self, node: Optional[TreeNode]) -> TreeNode:
|
||||
""" 左旋操作 """
|
||||
child = node.right
|
||||
grand_child = child.left
|
||||
# 以 child 为原点,将 node 向左旋转
|
||||
@@ -737,15 +737,15 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影
|
||||
|
||||
```javascript title="avl_tree.js"
|
||||
/* 左旋操作 */
|
||||
leftRotate(node) {
|
||||
#leftRotate(node) {
|
||||
const child = node.right;
|
||||
const grandChild = child.left;
|
||||
// 以 child 为原点,将 node 向左旋转
|
||||
child.left = node;
|
||||
node.right = grandChild;
|
||||
// 更新结点高度
|
||||
this.updateHeight(node);
|
||||
this.updateHeight(child);
|
||||
this.#updateHeight(node);
|
||||
this.#updateHeight(child);
|
||||
// 返回旋转后子树的根结点
|
||||
return child;
|
||||
}
|
||||
@@ -940,8 +940,8 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影
|
||||
=== "Python"
|
||||
|
||||
```python title="avl_tree.py"
|
||||
""" 执行旋转操作,使该子树重新恢复平衡 """
|
||||
def __rotate(self, node: Optional[TreeNode]) -> TreeNode:
|
||||
""" 执行旋转操作,使该子树重新恢复平衡 """
|
||||
# 获取结点 node 的平衡因子
|
||||
balance_factor = self.balance_factor(node)
|
||||
# 左偏树
|
||||
@@ -1005,29 +1005,29 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影
|
||||
|
||||
```javascript title="avl_tree.js"
|
||||
/* 执行旋转操作,使该子树重新恢复平衡 */
|
||||
rotate(node) {
|
||||
#rotate(node) {
|
||||
// 获取结点 node 的平衡因子
|
||||
const balanceFactor = this.balanceFactor(node);
|
||||
// 左偏树
|
||||
if (balanceFactor > 1) {
|
||||
if (this.balanceFactor(node.left) >= 0) {
|
||||
// 右旋
|
||||
return this.rightRotate(node);
|
||||
return this.#rightRotate(node);
|
||||
} else {
|
||||
// 先左旋后右旋
|
||||
node.left = this.leftRotate(node.left);
|
||||
return this.rightRotate(node);
|
||||
node.left = this.#leftRotate(node.left);
|
||||
return this.#rightRotate(node);
|
||||
}
|
||||
}
|
||||
// 右偏树
|
||||
if (balanceFactor < -1) {
|
||||
if (this.balanceFactor(node.right) <= 0) {
|
||||
// 左旋
|
||||
return this.leftRotate(node);
|
||||
return this.#leftRotate(node);
|
||||
} else {
|
||||
// 先右旋后左旋
|
||||
node.right = this.rightRotate(node.right);
|
||||
return this.leftRotate(node);
|
||||
node.right = this.#rightRotate(node.right);
|
||||
return this.#leftRotate(node);
|
||||
}
|
||||
}
|
||||
// 平衡树,无需旋转,直接返回
|
||||
@@ -1249,13 +1249,13 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影
|
||||
=== "Python"
|
||||
|
||||
```python title="avl_tree.py"
|
||||
""" 插入结点 """
|
||||
def insert(self, val) -> TreeNode:
|
||||
""" 插入结点 """
|
||||
self.root = self.__insert_helper(self.root, val)
|
||||
return self.root
|
||||
|
||||
""" 递归插入结点(辅助方法)"""
|
||||
def __insert_helper(self, node: Optional[TreeNode], val: int) -> TreeNode:
|
||||
""" 递归插入结点(辅助方法)"""
|
||||
if node is None:
|
||||
return TreeNode(val)
|
||||
# 1. 查找插入位置,并插入结点
|
||||
@@ -1309,20 +1309,20 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影
|
||||
```javascript title="avl_tree.js"
|
||||
/* 插入结点 */
|
||||
insert(val) {
|
||||
this.root = this.insertHelper(this.root, val);
|
||||
this.root = this.#insertHelper(this.root, val);
|
||||
return this.root;
|
||||
}
|
||||
|
||||
/* 递归插入结点(辅助方法) */
|
||||
insertHelper(node, val) {
|
||||
#insertHelper(node, val) {
|
||||
if (node === null) return new TreeNode(val);
|
||||
/* 1. 查找插入位置,并插入结点 */
|
||||
if (val < node.val) node.left = this.insertHelper(node.left, val);
|
||||
else if (val > node.val) node.right = this.insertHelper(node.right, val);
|
||||
if (val < node.val) node.left = this.#insertHelper(node.left, val);
|
||||
else if (val > node.val) node.right = this.#insertHelper(node.right, val);
|
||||
else return node; // 重复结点不插入,直接返回
|
||||
this.updateHeight(node); // 更新结点高度
|
||||
this.#updateHeight(node); // 更新结点高度
|
||||
/* 2. 执行旋转操作,使该子树重新恢复平衡 */
|
||||
node = this.rotate(node);
|
||||
node = this.#rotate(node);
|
||||
// 返回子树的根结点
|
||||
return node;
|
||||
}
|
||||
@@ -1571,13 +1571,13 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影
|
||||
=== "Python"
|
||||
|
||||
```python title="avl_tree.py"
|
||||
""" 删除结点 """
|
||||
def remove(self, val: int):
|
||||
""" 删除结点 """
|
||||
root = self.__remove_helper(self.root, val)
|
||||
return root
|
||||
|
||||
""" 递归删除结点(辅助方法) """
|
||||
def __remove_helper(self, node: Optional[TreeNode], val: int) -> Optional[TreeNode]:
|
||||
""" 递归删除结点(辅助方法) """
|
||||
if node is None:
|
||||
return None
|
||||
# 1. 查找结点,并删除之
|
||||
@@ -1603,8 +1603,8 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影
|
||||
# 2. 执行旋转操作,使该子树重新恢复平衡
|
||||
return self.__rotate(node)
|
||||
|
||||
""" 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) """
|
||||
def __get_inorder_next(self, node: Optional[TreeNode]) -> Optional[TreeNode]:
|
||||
""" 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) """
|
||||
if node is None:
|
||||
return None
|
||||
# 循环访问左子结点,直到叶结点时为最小结点,跳出
|
||||
@@ -1678,16 +1678,16 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影
|
||||
```javascript title="avl_tree.js"
|
||||
/* 删除结点 */
|
||||
remove(val) {
|
||||
this.root = this.removeHelper(this.root, val);
|
||||
this.root = this.#removeHelper(this.root, val);
|
||||
return this.root;
|
||||
}
|
||||
|
||||
/* 递归删除结点(辅助方法) */
|
||||
removeHelper(node, val) {
|
||||
#removeHelper(node, val) {
|
||||
if (node === null) return null;
|
||||
/* 1. 查找结点,并删除之 */
|
||||
if (val < node.val) node.left = this.removeHelper(node.left, val);
|
||||
else if (val > node.val) node.right = this.removeHelper(node.right, val);
|
||||
if (val < node.val) node.left = this.#removeHelper(node.left, val);
|
||||
else if (val > node.val) node.right = this.#removeHelper(node.right, val);
|
||||
else {
|
||||
if (node.left === null || node.right === null) {
|
||||
const child = node.left !== null ? node.left : node.right;
|
||||
@@ -1697,20 +1697,20 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影
|
||||
else node = child;
|
||||
} else {
|
||||
// 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结点
|
||||
const temp = this.getInOrderNext(node.right);
|
||||
node.right = this.removeHelper(node.right, temp.val);
|
||||
const temp = this.#getInOrderNext(node.right);
|
||||
node.right = this.#removeHelper(node.right, temp.val);
|
||||
node.val = temp.val;
|
||||
}
|
||||
}
|
||||
this.updateHeight(node); // 更新结点高度
|
||||
this.#updateHeight(node); // 更新结点高度
|
||||
/* 2. 执行旋转操作,使该子树重新恢复平衡 */
|
||||
node = this.rotate(node);
|
||||
node = this.#rotate(node);
|
||||
// 返回子树的根结点
|
||||
return node;
|
||||
}
|
||||
|
||||
/* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */
|
||||
getInOrderNext(node) {
|
||||
#getInOrderNext(node) {
|
||||
if (node === null) return node;
|
||||
// 循环访问左子结点,直到叶结点时为最小结点,跳出
|
||||
while (node.left !== null) {
|
||||
@@ -1745,7 +1745,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影
|
||||
return null;
|
||||
} else {
|
||||
// 子结点数量 = 1 ,直接删除 node
|
||||
node = child;
|
||||
node = child;
|
||||
}
|
||||
} else {
|
||||
// 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结点
|
||||
|
||||
@@ -80,8 +80,8 @@ comments: true
|
||||
=== "Python"
|
||||
|
||||
```python title="binary_search_tree.py"
|
||||
""" 查找结点 """
|
||||
def search(self, num: int) -> Optional[TreeNode]:
|
||||
""" 查找结点 """
|
||||
cur = self.root
|
||||
# 循环查找,越过叶结点后跳出
|
||||
while cur is not None:
|
||||
@@ -308,8 +308,8 @@ comments: true
|
||||
=== "Python"
|
||||
|
||||
```python title="binary_search_tree.py"
|
||||
""" 插入结点 """
|
||||
def insert(self, num: int) -> Optional[TreeNode]:
|
||||
""" 插入结点 """
|
||||
root = self.root
|
||||
# 若树为空,直接提前返回
|
||||
if root is None:
|
||||
@@ -392,7 +392,7 @@ comments: true
|
||||
else cur = cur.left;
|
||||
}
|
||||
// 插入结点 val
|
||||
let node = new Tree.TreeNode(num);
|
||||
let node = new TreeNode(num);
|
||||
if (pre.val < num) pre.right = node;
|
||||
else pre.left = node;
|
||||
return node;
|
||||
@@ -692,8 +692,8 @@ comments: true
|
||||
=== "Python"
|
||||
|
||||
```python title="binary_search_tree.py"
|
||||
""" 删除结点 """
|
||||
def remove(self, num: int) -> Optional[TreeNode]:
|
||||
""" 删除结点 """
|
||||
root = self.root
|
||||
# 若树为空,直接提前返回
|
||||
if root is None:
|
||||
@@ -734,8 +734,8 @@ comments: true
|
||||
cur.val = tmp
|
||||
return cur
|
||||
|
||||
""" 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) """
|
||||
def get_inorder_next(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
|
||||
""" 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) """
|
||||
if root is None:
|
||||
return root
|
||||
# 循环访问左子结点,直到叶结点时为最小结点,跳出
|
||||
|
||||
@@ -69,8 +69,8 @@ comments: true
|
||||
=== "Python"
|
||||
|
||||
```python title="binary_tree_bfs.py"
|
||||
""" 层序遍历 """
|
||||
def level_order(root: Optional[TreeNode]):
|
||||
""" 层序遍历 """
|
||||
# 初始化队列,加入根结点
|
||||
queue = collections.deque()
|
||||
queue.append(root)
|
||||
@@ -120,9 +120,9 @@ comments: true
|
||||
/* 层序遍历 */
|
||||
function levelOrder(root) {
|
||||
// 初始化队列,加入根结点
|
||||
let queue = [root];
|
||||
const queue = [root];
|
||||
// 初始化一个列表,用于保存遍历序列
|
||||
let list = [];
|
||||
const list = [];
|
||||
while (queue.length) {
|
||||
let node = queue.shift(); // 队列出队
|
||||
list.push(node.val); // 保存结点值
|
||||
@@ -337,8 +337,8 @@ comments: true
|
||||
=== "Python"
|
||||
|
||||
```python title="binary_tree_dfs.py"
|
||||
""" 前序遍历 """
|
||||
def pre_order(root: Optional[TreeNode]):
|
||||
""" 前序遍历 """
|
||||
if root is None:
|
||||
return
|
||||
# 访问优先级:根结点 -> 左子树 -> 右子树
|
||||
@@ -346,8 +346,8 @@ comments: true
|
||||
pre_order(root=root.left)
|
||||
pre_order(root=root.right)
|
||||
|
||||
""" 中序遍历 """
|
||||
def in_order(root: Optional[TreeNode]):
|
||||
""" 中序遍历 """
|
||||
if root is None:
|
||||
return
|
||||
# 访问优先级:左子树 -> 根结点 -> 右子树
|
||||
@@ -355,8 +355,8 @@ comments: true
|
||||
res.append(root.val)
|
||||
in_order(root=root.right)
|
||||
|
||||
""" 后序遍历 """
|
||||
def post_order(root: Optional[TreeNode]):
|
||||
""" 后序遍历 """
|
||||
if root is None:
|
||||
return
|
||||
# 访问优先级:左子树 -> 右子树 -> 根结点
|
||||
|
||||
Reference in New Issue
Block a user