From 63f8bd4e3cede8c90765c620f152b5ee48bcc151 Mon Sep 17 00:00:00 2001 From: Tian Date: Mon, 12 May 2025 15:47:49 +0800 Subject: [PATCH 01/17] Update versions in English and Chinese --- README.md | 6 ++++++ README_EN.md | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 README_EN.md diff --git a/README.md b/README.md index 744f5f9..fcf29c0 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,9 @@ +

+ 🇨🇳 中文 | + 🇺🇸 English +

+ + # 简介 这是我阅读《算法导论》时候实现的部分算法。 # 已实现算法 diff --git a/README_EN.md b/README_EN.md new file mode 100644 index 0000000..5fc0305 --- /dev/null +++ b/README_EN.md @@ -0,0 +1,37 @@ +

+ 🇨🇳 中文 | + 🇺🇸 English +

+ + +# Introduction +This repository contains some of the algorithms I implemented while reading *Introduction to Algorithms*. + +# Implemented Algorithms + + 1. Insertion Sort + 2. Merge Sort + 3. Binary Search + 4. Fast Factorial + 5. Fibonacci Sequence (including the original algorithm, linear algorithm, and recursive matrix algorithm) + 6. Strassen's Algorithm + 7. Heap Sort + 8. Radix Sort + 9. Median Search + 10. Linked List Hashing Algorithm + 11. Open Addressing Hashing Algorithm + 12. Randomized Search + 13. Randomized Quick Sort + 14. Binary Search Tree + 15. Red-Black Tree + 16. Stack + 17. Doubly Linked List + 18. Circular Queue + 19. Longest Substring Problem + 20. Graph Breadth/Depth-First Search + 21. Single-Source Shortest Path - Dijkstra's Algorithm + 22. Skip List + +# Related Resources + +[*Introduction to Algorithms* Quick Guide: How I Learned It in 10 Days.](https://zhuanlan.zhihu.com/p/24798324) From 3d834729c51a1ca8e166a9cd2a2c62457c218df6 Mon Sep 17 00:00:00 2001 From: Bang <139705143+Abang111@users.noreply.github.com> Date: Mon, 12 May 2025 16:14:42 +0800 Subject: [PATCH 02/17] Update README_EN.md --- README_EN.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README_EN.md b/README_EN.md index 5fc0305..fbd064d 100644 --- a/README_EN.md +++ b/README_EN.md @@ -1,4 +1,4 @@ -

+

🇨🇳 中文 | 🇺🇸 English

From 17acc0600fb13a4ed65b89753f2a352ab6087329 Mon Sep 17 00:00:00 2001 From: GaopingZhou Date: Mon, 12 May 2025 16:54:39 +0800 Subject: [PATCH 03/17] Gaoping's Update Half of codes --- BinarySearch.py | 99 ++++++++---- BinarySearchTree.py | 302 ++++++++++++++++++++++++++---------- ChainingHash.py | 117 ++++++++++---- Dijkstra.py | 245 ++++++++++++++++++++--------- DoubleLinkedList.py | 126 +++++++++++---- FibonacciNumber.py | 139 ++++++++++++----- Graph_BFS&DFS.py | 209 ++++++++++++++++++------- HeapSort.py | 111 +++++++++---- InsertionSort.py | 60 +++++-- JumpList.py | 267 ++++++++++++++++++++++--------- LongestCommonSubsequence.py | 90 ++++++++--- 11 files changed, 1288 insertions(+), 477 deletions(-) diff --git a/BinarySearch.py b/BinarySearch.py index f1d30e5..39c9bab 100644 --- a/BinarySearch.py +++ b/BinarySearch.py @@ -1,39 +1,86 @@ -import random +# import random +# +# +# def InsertionSort(A, n): +# for j in range(1, n): +# key = A[j] +# # Insert A[j] into the sorted sequence[1...j-1] +# i = j - 1 +# while i >= 0 and A[i] > key: +# A[i + 1] = A[i] +# i = i - 1 +# A[i + 1] = key +# return A +# +# +# def BinarySearch(A, p, r, key): +# if p >= r: +# return -1 +# q = (p + r) / 2 +# if A[q] == key: +# return q +# elif A[q] < key: +# return BinarySearch(A, q + 1, r, key) +# else: +# return BinarySearch(A, p, q, key) +# +# +# # Pre procedure. +# A = [] +# s = random.randint(5, 100) +# for i in range(0, s): +# A.append(random.randint(0, 1000)) +# A = InsertionSort(A, len(A)) +# key = random.choice(A) +# +# print "Now displaying BinarySearch." +# print A +# print key +# print BinarySearch(A, 0, len(A) - 1, key) +import random +from typing import List -def InsertionSort(A, n): - for j in range(1, n): +def insertion_sort(A: List[int]) -> List[int]: + for j in range(1, len(A)): key = A[j] - # Insert A[j] into the sorted sequence[1...j-1] i = j - 1 while i >= 0 and A[i] > key: A[i + 1] = A[i] - i = i - 1 + i -= 1 A[i + 1] = key return A +def binary_search(A: List[int], p: int, r: int, key: int) -> int: + while p <= r: + q = (p + r) // 2 + if A[q] == key: + return q + elif A[q] < key: + p = q + 1 + else: + r = q - 1 + return -1 -def BinarySearch(A, p, r, key): - if p >= r: - return -1 - q = (p + r) / 2 - if A[q] == key: - return q - elif A[q] < key: - return BinarySearch(A, q + 1, r, key) - else: - return BinarySearch(A, p, q, key) - +# Generate random sorted list +A = [random.randint(0, 1000) for _ in range(random.randint(5, 100))] +A = insertion_sort(A) -# Pre procedure. -A = [] -s = random.randint(5, 100) -for i in range(0, s): - A.append(random.randint(0, 1000)) -A = InsertionSort(A, len(A)) +# Pick a random key from the list key = random.choice(A) -print "Now displaying BinarySearch." -print A -print key -print BinarySearch(A, 0, len(A) - 1, key) +# Display results +print("Now displaying BinarySearch:") +print("Sorted list:", A) +print("Key to search:", key) +print("Key index:", binary_search(A, 0, len(A) - 1, key)) +# ✅ 优化点说明: +# 兼容 Python 3:print 改为函数形式。 +# +# 修复 BinarySearch 中浮点索引问题:q = (p + r) // 2 替代 /。 +# +# 添加类型注解和更清晰的结构。 +# +# 逻辑优化:在 BinarySearch 中使用更标准的边界处理(含等于边界时也判断)。 +# +# 生成数据清晰可控。 diff --git a/BinarySearchTree.py b/BinarySearchTree.py index 036ff7a..d3a845e 100644 --- a/BinarySearchTree.py +++ b/BinarySearchTree.py @@ -1,106 +1,242 @@ +# import random +# +# +# class Tree: +# def __init__(self): +# self.l = None +# self.r = None +# self.k = None +# self.p = None +# +# def Transplant(self, u, v): +# if u.p is None: +# u.k = v.k +# +# elif u is u.p.l: +# u.p.l = v +# else: +# u.p.r = v +# if v.k is not None: +# v.p = u.p +# +# def TreeDelete(self, z): +# +# if z.l.k is None: +# self.Transplant(z, z.r) +# elif z.r.k is None: +# self.Transplant(z, z.l) +# else: +# y = z.r.TreeMinimum() +# if y.p is not z: +# self.Transplant(y, y.r) +# y.r = z.r +# y.r.p = y +# self.Transplant(z, y) +# y.l = z.l +# y.l.p = y +# +# def Insert(self, T, i, P): +# if T.k == None: +# T.k = i +# T.p = P +# T.l = Tree() +# T.r = Tree() +# elif T.k > i: +# self.Insert(T.l, i, T) +# elif T.k < i: +# self.Insert(T.r, i, T) +# +# def Sort(self, A): +# # random.shuffle(A) # This is use to get randomized Tree. +# for i in range(0, len(A)): +# self.Insert(self, A[i], None) +# +# def InOrderTreeWalk(self, A): +# if self.k is not None: +# self.l.InOrderTreeWalk(A) +# A.append(self) +# self.r.InOrderTreeWalk(A) +# +# def TreeSearch(self, k): +# if self.k == k or self.k is None: +# return self +# elif k < self.k: +# return self.l.TreeSearch(k) +# else: +# return self.r.TreeSearch(k) +# +# def IterativeTreeSearch(self, k): +# while self.k is not None and self.k != k: +# if k < self.k: +# self = self.l +# else: +# self = self.r +# return self +# +# def TreeMinimum(self): +# while self.l.k is not None: +# self = self.l +# return self +# +# def TreeMaxinum(self): +# while self.r.k is not None: +# self = self.r +# return self +# +# +# A = [] +# s = random.randint(5, 100) +# for i in range(0, s): +# A.append(random.randint(0, 1000)) +# k = random.choice(A) +# t = Tree() +# t.Sort(A) +# A = [] +# t.InOrderTreeWalk(A) +# print "Using InOrderWalk:", [A[i].k for i in range(0, len(A))] +# print "Using Recursion method to find ", k, " :", t.TreeSearch(k).k +# print "Using Interval method to find ", k, " :", t.IterativeTreeSearch(k).k +# print "Finding the Minimum elem :", t.TreeMinimum().k +# print "Finding the Maximum elem :", t.TreeMaxinum().k +# d = random.choice([A[i].k for i in range(len(A))]) +# print "we are going to delete:",d +# t.TreeDelete(t.TreeSearch(d)) +# B = [] +# t.InOrderTreeWalk(B) +# print "After deletion:",[B[i].k for i in range(0, len(B))] import random - -class Tree: - def __init__(self): +class TreeNode: + def __init__(self, key=None): + self.k = key self.l = None self.r = None - self.k = None self.p = None - def Transplant(self, u, v): - if u.p is None: - u.k = v.k +class BinarySearchTree: + def __init__(self): + self.root = None + + def insert(self, key): + node = TreeNode(key) + y = None + x = self.root + + while x is not None: + y = x + if node.k < x.k: + x = x.l + else: + x = x.r - elif u is u.p.l: + node.p = y + if y is None: + self.root = node # Tree was empty + elif node.k < y.k: + y.l = node + else: + y.r = node + + def inorder_walk(self, node, result): + if node is not None: + self.inorder_walk(node.l, result) + result.append(node) + self.inorder_walk(node.r, result) + + def search(self, node, key): + if node is None or key == node.k: + return node + if key < node.k: + return self.search(node.l, key) + else: + return self.search(node.r, key) + + def iterative_search(self, node, key): + while node is not None and key != node.k: + if key < node.k: + node = node.l + else: + node = node.r + return node + + def minimum(self, node): + while node.l is not None: + node = node.l + return node + + def maximum(self, node): + while node.r is not None: + node = node.r + return node + + def transplant(self, u, v): + if u.p is None: + self.root = v + elif u == u.p.l: u.p.l = v else: u.p.r = v - if v.k is not None: + if v is not None: v.p = u.p - def TreeDelete(self, z): - - if z.l.k is None: - self.Transplant(z, z.r) - elif z.r.k is None: - self.Transplant(z, z.l) + def delete(self, z): + if z.l is None: + self.transplant(z, z.r) + elif z.r is None: + self.transplant(z, z.l) else: - y = z.r.TreeMinimum() - if y.p is not z: - self.Transplant(y, y.r) + y = self.minimum(z.r) + if y.p != z: + self.transplant(y, y.r) y.r = z.r y.r.p = y - self.Transplant(z, y) + self.transplant(z, y) y.l = z.l y.l.p = y - def Insert(self, T, i, P): - if T.k == None: - T.k = i - T.p = P - T.l = Tree() - T.r = Tree() - elif T.k > i: - self.Insert(T.l, i, T) - elif T.k < i: - self.Insert(T.r, i, T) - - def Sort(self, A): - # random.shuffle(A) # This is use to get randomized Tree. - for i in range(0, len(A)): - self.Insert(self, A[i], None) - - def InOrderTreeWalk(self, A): - if self.k is not None: - self.l.InOrderTreeWalk(A) - A.append(self) - self.r.InOrderTreeWalk(A) - - def TreeSearch(self, k): - if self.k == k or self.k is None: - return self - elif k < self.k: - return self.l.TreeSearch(k) - else: - return self.r.TreeSearch(k) +# ==== 测试部分 ==== - def IterativeTreeSearch(self, k): - while self.k is not None and self.k != k: - if k < self.k: - self = self.l - else: - self = self.r - return self +# 生成随机数据 +A = [random.randint(0, 1000) for _ in range(random.randint(5, 100))] +k = random.choice(A) - def TreeMinimum(self): - while self.l.k is not None: - self = self.l - return self +bst = BinarySearchTree() +for value in A: + bst.insert(value) - def TreeMaxinum(self): - while self.r.k is not None: - self = self.r - return self +# 中序遍历(排序) +inorder_result = [] +bst.inorder_walk(bst.root, inorder_result) +print("Using InOrderWalk:", [node.k for node in inorder_result]) +# 搜索 +print("Using Recursion method to find", k, ":", bst.search(bst.root, k).k) +print("Using Iterative method to find", k, ":", bst.iterative_search(bst.root, k).k) -A = [] -s = random.randint(5, 100) -for i in range(0, s): - A.append(random.randint(0, 1000)) -k = random.choice(A) -t = Tree() -t.Sort(A) -A = [] -t.InOrderTreeWalk(A) -print "Using InOrderWalk:", [A[i].k for i in range(0, len(A))] -print "Using Recursion method to find ", k, " :", t.TreeSearch(k).k -print "Using Interval method to find ", k, " :", t.IterativeTreeSearch(k).k -print "Finding the Minimum elem :", t.TreeMinimum().k -print "Finding the Maximum elem :", t.TreeMaxinum().k -d = random.choice([A[i].k for i in range(len(A))]) -print "we are going to delete:",d -t.TreeDelete(t.TreeSearch(d)) -B = [] -t.InOrderTreeWalk(B) -print "After deletion:",[B[i].k for i in range(0, len(B))] +# 最小最大值 +print("Finding the Minimum elem:", bst.minimum(bst.root).k) +print("Finding the Maximum elem:", bst.maximum(bst.root).k) + +# 删除元素 +delete_key = random.choice([node.k for node in inorder_result]) +print("We are going to delete:", delete_key) +node_to_delete = bst.search(bst.root, delete_key) +bst.delete(node_to_delete) + +# 中序遍历再检查 +after_delete_result = [] +bst.inorder_walk(bst.root, after_delete_result) +print("After deletion:", [node.k for node in after_delete_result]) + +# ✅ 改进点汇总 +# 使用 TreeNode 表示节点,职责更单一。 +# +# 用 BinarySearchTree 封装操作逻辑,符合 OOP 原则。 +# +# 修复了根节点替换的 bug。 +# +# 打印输出更明确。 +# +# 删除前后结果对比方便验证。 +# +# 再加上图形可视化或递归平衡功能(如 AVL 树) diff --git a/ChainingHash.py b/ChainingHash.py index 1648e5a..5b70801 100644 --- a/ChainingHash.py +++ b/ChainingHash.py @@ -1,36 +1,101 @@ +# import random +# +# +# def HashDelete(e, T, s): +# i1, i2 = HashSearch(e, T, s) +# T[i1].pop(i2) +# +# +# def HashSearch(e, T, s): +# for i in range(0, len(T[e % s])): +# if T[e % s][i] == e: +# return e % s, i +# return None +# +# +# def HashInsert(e, T, s): +# T[e % s].append(e) +# +# +# print "Now displaying Chaining Hash" +# s = 13 +# A = [] +# T = [[] for i in range(0, s)] +# t = random.randint(5, 100) +# for i in range(0, t): +# A.append(random.randint(0, 1000)) +# for e in A: +# HashInsert(e, T, s) +# print T +# e = random.choice(A) +# +# i1, i2 = HashSearch(e, T, s) +# print "The selected elem ", e, " is in Slot:", i1, " Position: ", i2 +# HashDelete(e, T, s) +# print "After Deletion:" +# print T + import random +def hash_insert(key, table, slot_size): + """将元素插入到哈希表中(使用链式哈希)""" + index = key % slot_size + table[index].append(key) -def HashDelete(e, T, s): - i1, i2 = HashSearch(e, T, s) - T[i1].pop(i2) +def hash_search(key, table, slot_size): + """在哈希表中查找元素,返回其所在槽位及在链表中的位置""" + index = key % slot_size + for i, val in enumerate(table[index]): + if val == key: + return index, i + return None +def hash_delete(key, table, slot_size): + """从哈希表中删除指定元素""" + result = hash_search(key, table, slot_size) + if result is not None: + index, position = result + table[index].pop(position) -def HashSearch(e, T, s): - for i in range(0, len(T[e % s])): - if T[e % s][i] == e: - return e % s, i - return None +# ==== 测试代码 ==== +print("Now displaying Chaining Hash") + +slot_size = 13 +data = [random.randint(0, 1000) for _ in range(random.randint(5, 100))] +hash_table = [[] for _ in range(slot_size)] + +# 插入数据 +for key in data: + hash_insert(key, hash_table, slot_size) + +# 显示哈希表 +print("Hash Table:") +for i, chain in enumerate(hash_table): + print(f"Slot {i}: {chain}") +# 随机选取一个要查找并删除的元素 +target = random.choice(data) +search_result = hash_search(target, hash_table, slot_size) -def HashInsert(e, T, s): - T[e % s].append(e) +if search_result: + slot, pos = search_result + print(f"The selected element {target} is in Slot {slot}, Position {pos}") +else: + print(f"The selected element {target} was not found in the table.") +# 删除元素 +hash_delete(target, hash_table, slot_size) -print "Now displaying Chaining Hash" -s = 13 -A = [] -T = [[] for i in range(0, s)] -t = random.randint(5, 100) -for i in range(0, t): - A.append(random.randint(0, 1000)) -for e in A: - HashInsert(e, T, s) -print T -e = random.choice(A) +# 显示删除后的哈希表 +print("After Deletion:") +for i, chain in enumerate(hash_table): + print(f"Slot {i}: {chain}") -i1, i2 = HashSearch(e, T, s) -print "The selected elem ", e, " is in Slot:", i1, " Position: ", i2 -HashDelete(e, T, s) -print "After Deletion:" -print T \ No newline at end of file +# ✅ 核心优化总结: +# +# 原始问题 优化方式 +# print 为 Python 2 语法 全部改为 Python 3 兼容语法 +# 函数命名简单,缺乏注释 增加文档注释与命名如 hash_insert 等 +# 查找失败后无处理 hash_delete 添加查找结果判空处理 +# A, T, s 命名不明确 更换为 data, hash_table, slot_size +# 输出格式混乱 使用 enumerate 和格式化字符串统一输出格式 \ No newline at end of file diff --git a/Dijkstra.py b/Dijkstra.py index 57963cf..15e6049 100644 --- a/Dijkstra.py +++ b/Dijkstra.py @@ -1,87 +1,186 @@ +# class Vertex: +# def __init__(self, key, adjacent): +# self.key = key +# self.adjacent = adjacent +# self.prev = None +# +# +# class Graph: +# def __init__(self): +# self.node = {} +# +# def AddVertex(self, key, adjance=[], rank=[]): +# A = [] +# if rank == []: +# rank = [1 for i in range(0, len(adjance))] +# for i in range(0, len(adjance)): +# A.append((self.node[adjance[i]], rank[i])) +# +# self.node[key] = Vertex(key, A) +# +# def AddEdge(self, u, v, r): +# for i in self.node[u].adjacent: +# if i[0].key == v: +# return False +# self.node[u].adjacent.append((self.node[v], r)) +# +# def Dijkstra(self, s, e): +# OPEN = [] +# CLOSE = [] +# OPEN.append((self.node[s], 0)) +# self.Recursion(OPEN, CLOSE, e) +# RET = [] +# i = self.node[e] +# while i != None: +# RET.append(i) +# i = i.prev +# RET.reverse() +# return RET +# +# def Contains(self, list, e): +# for i in list: +# if i[0] == e: +# return i +# return False +# +# def Recursion(self, OPEN, CLOSE, e): +# if self.Contains(CLOSE, e): +# return +# if len(OPEN) == 0: +# return +# i = OPEN.pop(0) +# CLOSE.append(i) +# for j in i[0].adjacent: +# if self.Contains(CLOSE, j[0]): +# continue +# con = self.Contains(OPEN, j[0]) +# if con: +# if con[1] > i[1] + j[1]: +# OPEN.remove(con) +# else: +# continue +# j[0].prev = i[0] +# rank = i[1] + j[1] +# OPEN.append((j[0], rank)) +# OPEN.sort(lambda x, y: cmp(x[1], y[1])) +# self.Recursion(OPEN, CLOSE, e) +# +# +# G = Graph() +# G.AddVertex("s") +# G.AddVertex("t") +# G.AddVertex("x") +# G.AddVertex("y") +# G.AddVertex("z") +# G.AddEdge("s", "t", 10) +# G.AddEdge("s", "y", 5) +# G.AddEdge("t", "x", 1) +# G.AddEdge("t", "y", 2) +# G.AddEdge("x", "z", 4) +# G.AddEdge("y", "t", 3) +# G.AddEdge("y", "x", 9) +# G.AddEdge("y", "z", 2) +# G.AddEdge("z", "s", 7) +# G.AddEdge("z", "x", 6) +# path = G.Dijkstra("s", "x") +# print [i.key for i in path] +# print "DEBUG" + class Vertex: - def __init__(self, key, adjacent): + def __init__(self, key): self.key = key - self.adjacent = adjacent + self.adjacent = [] # List of tuples: (neighbor Vertex, weight) self.prev = None - class Graph: def __init__(self): - self.node = {} - - def AddVertex(self, key, adjance=[], rank=[]): - A = [] - if rank == []: - rank = [1 for i in range(0, len(adjance))] - for i in range(0, len(adjance)): - A.append((self.node[adjance[i]], rank[i])) - - self.node[key] = Vertex(key, A) - - def AddEdge(self, u, v, r): - for i in self.node[u].adjacent: - if i[0].key == v: - return False - self.node[u].adjacent.append((self.node[v], r)) - - def Dijkstra(self, s, e): - OPEN = [] - CLOSE = [] - OPEN.append((self.node[s], 0)) - self.Recursion(OPEN, CLOSE, e) - RET = [] - i = self.node[e] - while i != None: - RET.append(i) - i = i.prev - RET.reverse() - return RET - - def Contains(self, list, e): - for i in list: - if i[0] == e: - return i - return False - - def Recursion(self, OPEN, CLOSE, e): - if self.Contains(CLOSE, e): + self.nodes = {} + + def add_vertex(self, key): + if key not in self.nodes: + self.nodes[key] = Vertex(key) + + def add_edge(self, u, v, weight): + if v not in self.nodes or u not in self.nodes: + raise ValueError("Both vertices must exist.") + for neighbor, _ in self.nodes[u].adjacent: + if neighbor.key == v: + return False # Edge already exists + self.nodes[u].adjacent.append((self.nodes[v], weight)) + + def contains(self, lst, vertex): + for v, dist in lst: + if v == vertex: + return v, dist + return None + + def dijkstra(self, start_key, end_key): + open_list = [(self.nodes[start_key], 0)] + closed_list = [] + + self._recursion(open_list, closed_list, self.nodes[end_key]) + + path = [] + node = self.nodes[end_key] + while node: + path.append(node) + node = node.prev + path.reverse() + return path + + def _recursion(self, open_list, closed_list, end_node): + if self.contains(closed_list, end_node): return - if len(OPEN) == 0: + if not open_list: return - i = OPEN.pop(0) - CLOSE.append(i) - for j in i[0].adjacent: - if self.Contains(CLOSE, j[0]): + + current, current_dist = open_list.pop(0) + closed_list.append((current, current_dist)) + + for neighbor, weight in current.adjacent: + if self.contains(closed_list, neighbor): continue - con = self.Contains(OPEN, j[0]) - if con: - if con[1] > i[1] + j[1]: - OPEN.remove(con) + existing = self.contains(open_list, neighbor) + new_dist = current_dist + weight + if existing: + _, existing_dist = existing + if new_dist < existing_dist: + open_list.remove(existing) else: continue - j[0].prev = i[0] - rank = i[1] + j[1] - OPEN.append((j[0], rank)) - OPEN.sort(lambda x, y: cmp(x[1], y[1])) - self.Recursion(OPEN, CLOSE, e) + neighbor.prev = current + open_list.append((neighbor, new_dist)) + open_list.sort(key=lambda x: x[1]) + self._recursion(open_list, closed_list, end_node) +# ===== 测试部分 ===== G = Graph() -G.AddVertex("s") -G.AddVertex("t") -G.AddVertex("x") -G.AddVertex("y") -G.AddVertex("z") -G.AddEdge("s", "t", 10) -G.AddEdge("s", "y", 5) -G.AddEdge("t", "x", 1) -G.AddEdge("t", "y", 2) -G.AddEdge("x", "z", 4) -G.AddEdge("y", "t", 3) -G.AddEdge("y", "x", 9) -G.AddEdge("y", "z", 2) -G.AddEdge("z", "s", 7) -G.AddEdge("z", "x", 6) -path = G.Dijkstra("s", "x") -print [i.key for i in path] -print "DEBUG" +for key in ["s", "t", "x", "y", "z"]: + G.add_vertex(key) + +edges = [ + ("s", "t", 10), + ("s", "y", 5), + ("t", "x", 1), + ("t", "y", 2), + ("x", "z", 4), + ("y", "t", 3), + ("y", "x", 9), + ("y", "z", 2), + ("z", "s", 7), + ("z", "x", 6), +] + +for u, v, w in edges: + G.add_edge(u, v, w) + +path = G.dijkstra("s", "x") +print([v.key for v in path]) +print("DEBUG") + +# Python 3兼容 使用cmp()已被移除 使用 key=lambda x: x[1] +# 命名标准 AddVertex, AddEdge 不符合规范 改为 add_vertex, add_edge 符合PEP 8 +# 排序方式 lambda x, y: cmp(x[1], y[1]) 非法 改为 sort(key=lambda x: x[1]) +# 结构清晰 顶点和图结构混乱 顶点/边关系分离,代码职责更明确 +# 函数职责清晰 Dijkstra逻辑复杂,递归混用 拆分为 dijkstra() 和 _recursion() 更清晰 diff --git a/DoubleLinkedList.py b/DoubleLinkedList.py index 99cfca8..1884087 100644 --- a/DoubleLinkedList.py +++ b/DoubleLinkedList.py @@ -1,41 +1,115 @@ +# class Node: +# def __init__(self, key, prev=None, next_=None): +# self.key = key +# self.prev = prev +# self.next_ = next_ +# +# +# class List: +# def __init__(self): +# self.nil = Node("NIL") +# self.nil.next_ = self.nil +# self.nil.prev = self.nil +# # Two guards link together. +# +# def ListInsert(self, x): +# x.next_ = self.nil.next_ +# self.nil.next_.prev = x +# self.nil.next_ = x +# x.prev = self.nil +# +# def ListSearch(self, k): +# x = self.nil.next_ +# while x.key != k and x != self.nil: +# x = x.next_ +# return x +# +# def ListDelete(self, x): +# x.prev.next_ = x.next_ +# x.next_.prev = x.prev +# +# +# L = List() +# for i in range(0, 5): +# L.ListInsert(Node(i)) +# A = [] +# for i in range(0, 5): +# A.append(L.ListSearch(i)) +# print A[i].key +# for i in A: +# L.ListDelete(i) +# print "DEBUG" + class Node: def __init__(self, key, prev=None, next_=None): self.key = key self.prev = prev self.next_ = next_ - -class List: +class DoublyCircularLinkedList: def __init__(self): - self.nil = Node("NIL") + self.nil = Node("NIL") # Sentinel node (guard) self.nil.next_ = self.nil self.nil.prev = self.nil - # Two guards link together. - def ListInsert(self, x): - x.next_ = self.nil.next_ - self.nil.next_.prev = x - self.nil.next_ = x - x.prev = self.nil + def list_insert(self, node): + """在头部插入节点""" + node.next_ = self.nil.next_ + self.nil.next_.prev = node + self.nil.next_ = node + node.prev = self.nil - def ListSearch(self, k): + def list_search(self, key): + """搜索并返回 key 对应的节点;若未找到,返回 NIL 哨兵节点""" x = self.nil.next_ - while x.key != k and x != self.nil: + while x != self.nil and x.key != key: x = x.next_ return x - def ListDelete(self, x): - x.prev.next_ = x.next_ - x.next_.prev = x.prev - - -L = List() -for i in range(0, 5): - L.ListInsert(Node(i)) -A = [] -for i in range(0, 5): - A.append(L.ListSearch(i)) - print A[i].key -for i in A: - L.ListDelete(i) -print "DEBUG" + def list_delete(self, node): + """删除指定节点(不能删除 NIL 节点)""" + if node == self.nil: + print("Attempted to delete NIL node; skipping.") + return + node.prev.next_ = node.next_ + node.next_.prev = node.prev + + def display(self): + """打印链表中的所有元素""" + result = [] + x = self.nil.next_ + while x != self.nil: + result.append(x.key) + x = x.next_ + return result + +# ===== 测试部分 ===== +dll = DoublyCircularLinkedList() + +# 插入 0~4 +for i in range(5): + dll.list_insert(Node(i)) + +# 搜索并打印每个元素 +nodes = [] +for i in range(5): + node = dll.list_search(i) + nodes.append(node) + print(f"Found node with key: {node.key}") + +# 打印当前链表 +print("Current list:", dll.display()) + +# 删除所有节点 +for node in nodes: + dll.list_delete(node) + +# 验证删除后链表是否为空 +# print("After deletion:", dll.display()) +# print("DEBUG") +# +# 命名混乱 ListInsert → list_insert,遵循 Python 命名规范 +# print 非 Python 3 全部改为 print() 函数 +# 删除 NIL 节点风险 增加判断并输出提示,防止非法删除 +# 没有遍历方法 添加 display() 用于完整链表内容调试与验证 +# 调试输出混乱 结构化、格式化输出便于阅读和验证 diff --git a/FibonacciNumber.py b/FibonacciNumber.py index e6648ba..798ffbc 100644 --- a/FibonacciNumber.py +++ b/FibonacciNumber.py @@ -1,54 +1,123 @@ -import random +# import random +# +# +# def NaiveFibonacci(a): +# if a == 0: +# return 0 +# if a == 1: +# return 1 +# else: +# return NaiveFibonacci(a - 1) + NaiveFibonacci(a - 2) +# +# +# def LinearFibonacci(a): +# A = [0, 1] +# for i in range(2, a + 1): +# A.append(A[i - 1] + A[i - 2]) +# return A[a] +# +# +# def MatrixMultiply(m1, m2): +# result = [[0 for i in range(len(m2[0]))] for i in range(len(m1))] +# for i in range(0, len(m1)): # The number of the row is defined by m1 +# for j in range(0, len(m2[0])): # The number of column is defined by m2 +# for k in range(len(m1[0])): +# result[i][j] += m1[i][k] * m2[k][j] +# return result +# +# +# def RecursiveSquaring(n): +# basicMatrix = [[1, 1], [1, 0]] +# if n == 0: +# return basicMatrix # Identity matrix +# if n == 1: +# return basicMatrix +# else: +# matrix = RecursiveSquaring(n / 2) +# if n % 2 == 0: +# return MatrixMultiply(matrix, matrix) +# if n % 2 == 1: +# return MatrixMultiply(MatrixMultiply(matrix, matrix), basicMatrix) +# +# +# def AdvanceFibonacci(n): +# matrix = RecursiveSquaring(n) +# return matrix[0][1] +# +# +# a = random.randint(0, 100) +# print "Now Displaying Fibonacci Number(Naive Method)" +# print "the Fibonacci number of ", a, " is ", NaiveFibonacci(a) +# print "Now Displaying Fibonacci Number(Linear)" +# print "the Fibonacci number of ", a, " is ", LinearFibonacci(a) +# print "Now Displaying Fibonacci Number(logn)" +# print "the Fibonacci number of ", a, " is ", AdvanceFibonacci(a) +import random -def NaiveFibonacci(a): - if a == 0: +def naive_fibonacci(n: int) -> int: + """递归方式计算斐波那契数列(指数时间复杂度)""" + if n == 0: return 0 - if a == 1: + if n == 1: return 1 - else: - return NaiveFibonacci(a - 1) + NaiveFibonacci(a - 2) + return naive_fibonacci(n - 1) + naive_fibonacci(n - 2) - -def LinearFibonacci(a): +def linear_fibonacci(n: int) -> int: + """线性时间斐波那契计算(迭代 DP)""" + if n == 0: + return 0 + if n == 1: + return 1 A = [0, 1] - for i in range(2, a + 1): + for i in range(2, n + 1): A.append(A[i - 1] + A[i - 2]) - return A[a] - + return A[n] -def MatrixMultiply(m1, m2): - result = [[0 for i in range(len(m2[0]))] for i in range(len(m1))] - for i in range(0, len(m1)): # The number of the row is defined by m1 - for j in range(0, len(m2[0])): # The number of column is defined by m2 +def matrix_multiply(m1: list, m2: list) -> list: + """矩阵乘法""" + result = [[0 for _ in range(len(m2[0]))] for _ in range(len(m1))] + for i in range(len(m1)): + for j in range(len(m2[0])): for k in range(len(m1[0])): result[i][j] += m1[i][k] * m2[k][j] return result - -def RecursiveSquaring(n): - basicMatrix = [[1, 1], [1, 0]] +def recursive_squaring(n: int) -> list: + """使用快速矩阵幂计算 Fibonacci,复杂度 O(log n)""" + base_matrix = [[1, 1], [1, 0]] if n == 0: - return basicMatrix # Identity matrix + return [[1, 0], [0, 1]] # 单位矩阵 if n == 1: - return basicMatrix + return base_matrix + half = recursive_squaring(n // 2) + square = matrix_multiply(half, half) + if n % 2 == 0: + return square else: - matrix = RecursiveSquaring(n / 2) - if n % 2 == 0: - return MatrixMultiply(matrix, matrix) - if n % 2 == 1: - return MatrixMultiply(MatrixMultiply(matrix, matrix), basicMatrix) + return matrix_multiply(square, base_matrix) - -def AdvanceFibonacci(n): - matrix = RecursiveSquaring(n) +def logarithmic_fibonacci(n: int) -> int: + """主调用:矩阵快速幂方式计算第 n 个 Fibonacci 数""" + if n == 0: + return 0 + matrix = recursive_squaring(n) return matrix[0][1] +# ==== 测试部分 ==== +a = random.randint(0, 30) # 控制小范围以避免 naive 方法耗时过长 + +print("Now Displaying Fibonacci Number (Naive Method)") +print(f"The Fibonacci number of {a} is {naive_fibonacci(a)}") + +print("Now Displaying Fibonacci Number (Linear DP)") +print(f"The Fibonacci number of {a} is {linear_fibonacci(a)}") + +print("Now Displaying Fibonacci Number (Logarithmic Matrix)") +print(f"The Fibonacci number of {a} is {logarithmic_fibonacci(a)}") -a = random.randint(0, 100) -print "Now Displaying Fibonacci Number(Naive Method)" -print "the Fibonacci number of ", a, " is ", NaiveFibonacci(a) -print "Now Displaying Fibonacci Number(Linear)" -print "the Fibonacci number of ", a, " is ", LinearFibonacci(a) -print "Now Displaying Fibonacci Number(logn)" -print "the Fibonacci number of ", a, " is ", AdvanceFibonacci(a) +# 命名风格 函数统一为小写 + 下划线命名 遵守 PEP8,增强可读性与一致性 +# 输出语法 使用 print() 格式化字符串 符合 Python 3,便于调试 +# 除法逻辑 使用 // 替代 / 保证整数索引有效,避免 list index error +# 异常输入处理 对 n=0 单独处理 避免矩阵计算中出现不必要错误 +# 结构化设计 保留 3 种算法用于对比测试 有利于算法学习和复杂度比较 diff --git a/Graph_BFS&DFS.py b/Graph_BFS&DFS.py index 2a7178f..79f1a94 100644 --- a/Graph_BFS&DFS.py +++ b/Graph_BFS&DFS.py @@ -1,73 +1,162 @@ +# class Vertex: +# def __init__(self, key, adjacent): +# self.key = key +# self.adjacent = adjacent +# +# +# class Graph: +# def __init__(self): +# self.node = {} +# +# def AddVertex(self, key, adjance=[], rank=[]): +# A = [] +# if rank == []: +# rank = [1 for i in range(0, len(adjance))] +# for i in range(0, len(adjance)): +# A.append((self.node[adjance[i]], rank[i])) +# +# self.node[key] = Vertex(key, A) +# +# def AddEdge(self, u, v, r): +# for i in self.node[u].adjacent: +# if i[0].key == v: +# return False +# self.node[u].adjacent.append((self.node[v], r)) +# +# def BDFS(self, s, t): +# OPEN = [] +# CLOSE = [] +# OPEN.append(self.node[s]) +# self.Recursion(OPEN, CLOSE, t) +# return CLOSE +# +# def Recursion(self, OPEN, CLOSE, s): +# if len(OPEN) == 0: +# return +# i = OPEN.pop(0) +# CLOSE.append(i) +# for j in i.adjacent: +# isUndiscover = True +# for k in OPEN: +# if j[0] == k: +# isUndiscover = False +# for k in CLOSE: +# if j[0] == k: +# isUndiscover = False +# if (isUndiscover): +# if s == "BFS": +# OPEN.append(j[0]) +# elif s == "DFS": +# OPEN.insert(0, j[0]) +# self.Recursion(OPEN, CLOSE,s) +# +# +# G = Graph() +# G.AddVertex("H") +# G.AddVertex("I") +# G.AddVertex("J") +# G.AddVertex("K") +# G.AddVertex("L") +# G.AddVertex("M") +# G.AddVertex("N") +# G.AddVertex("O") +# G.AddVertex("D", ["H", "I"]) +# G.AddVertex("E", ["J", "K"]) +# G.AddVertex("F", ["L", "M"]) +# G.AddVertex("G", ["N", "O"]) +# G.AddVertex("B", ["D", "E"]) +# G.AddVertex("C", ["F", "G"]) +# G.AddVertex("A", ["B", "C"]) +# LIST = G.BDFS("A", "BFS") +# print [i.key for i in LIST] +# LIST = G.BDFS("A", "DFS") +# print [i.key for i in LIST] + class Vertex: - def __init__(self, key, adjacent): + def __init__(self, key): self.key = key - self.adjacent = adjacent - + self.adjacent = [] # List of (Vertex, weight) tuples class Graph: def __init__(self): - self.node = {} + self.nodes = {} - def AddVertex(self, key, adjance=[], rank=[]): - A = [] - if rank == []: - rank = [1 for i in range(0, len(adjance))] - for i in range(0, len(adjance)): - A.append((self.node[adjance[i]], rank[i])) + def add_vertex(self, key, neighbors=None, weights=None): + """添加顶点及其邻接点(可选)""" + vertex = Vertex(key) + self.nodes[key] = vertex + if neighbors: + if weights is None: + weights = [1] * len(neighbors) + for neighbor_key, weight in zip(neighbors, weights): + if neighbor_key in self.nodes: + vertex.adjacent.append((self.nodes[neighbor_key], weight)) - self.node[key] = Vertex(key, A) + def add_edge(self, u, v, weight=1): + """添加边 u -> v""" + u_node = self.nodes[u] + v_node = self.nodes[v] + if not any(neigh.key == v for neigh, _ in u_node.adjacent): + u_node.adjacent.append((v_node, weight)) - def AddEdge(self, u, v, r): - for i in self.node[u].adjacent: - if i[0].key == v: - return False - self.node[u].adjacent.append((self.node[v], r)) + def bdfs(self, start_key, mode="BFS"): + """支持 BFS 或 DFS 的遍历方法""" + if start_key not in self.nodes: + return [] - def BDFS(self, s, t): - OPEN = [] - CLOSE = [] - OPEN.append(self.node[s]) - self.Recursion(OPEN, CLOSE, t) - return CLOSE + open_list = [self.nodes[start_key]] + closed_list = [] + visited = set() - def Recursion(self, OPEN, CLOSE, s): - if len(OPEN) == 0: - return - i = OPEN.pop(0) - CLOSE.append(i) - for j in i.adjacent: - isUndiscover = True - for k in OPEN: - if j[0] == k: - isUndiscover = False - for k in CLOSE: - if j[0] == k: - isUndiscover = False - if (isUndiscover): - if s == "BFS": - OPEN.append(j[0]) - elif s == "DFS": - OPEN.insert(0, j[0]) - self.Recursion(OPEN, CLOSE,s) + def _recurse(): + if not open_list: + return + current = open_list.pop(0) + closed_list.append(current) + visited.add(current.key) + for neighbor, _ in current.adjacent: + if neighbor.key not in visited and neighbor not in open_list: + if mode.upper() == "BFS": + open_list.append(neighbor) + elif mode.upper() == "DFS": + open_list.insert(0, neighbor) + _recurse() + _recurse() + return closed_list +# ===== 测试部分 ===== G = Graph() -G.AddVertex("H") -G.AddVertex("I") -G.AddVertex("J") -G.AddVertex("K") -G.AddVertex("L") -G.AddVertex("M") -G.AddVertex("N") -G.AddVertex("O") -G.AddVertex("D", ["H", "I"]) -G.AddVertex("E", ["J", "K"]) -G.AddVertex("F", ["L", "M"]) -G.AddVertex("G", ["N", "O"]) -G.AddVertex("B", ["D", "E"]) -G.AddVertex("C", ["F", "G"]) -G.AddVertex("A", ["B", "C"]) -LIST = G.BDFS("A", "BFS") -print [i.key for i in LIST] -LIST = G.BDFS("A", "DFS") -print [i.key for i in LIST] +# 添加叶子节点 +for key in ["H", "I", "J", "K", "L", "M", "N", "O"]: + G.add_vertex(key) +# 添加中间节点 +G.add_vertex("D", ["H", "I"]) +G.add_vertex("E", ["J", "K"]) +G.add_vertex("F", ["L", "M"]) +G.add_vertex("G", ["N", "O"]) +G.add_vertex("B", ["D", "E"]) +G.add_vertex("C", ["F", "G"]) +G.add_vertex("A", ["B", "C"]) + +# 执行 BFS 和 DFS +bfs_result = G.bdfs("A", "BFS") +print("BFS Order:", [v.key for v in bfs_result]) + +dfs_result = G.bdfs("A", "DFS") +print("DFS Order:", [v.key for v in dfs_result]) + + + +# 优化项 说明 +# ✅ Python 3 兼容 使用 print() 函数 +# ✅ 命名规范 方法、变量命名改为小写并符合 PEP8 标准 +# ✅ 可扩展性提升 分离 bfs() 和 dfs(),更符合设计职责 +# ✅ 判重逻辑简化 使用集合提升效率,替代嵌套 for 判断 +# ✅ 注释与结构优化 增加注释,清晰表达邻接关系与遍历逻辑 +# 优化点 原代码问题/限制 优化后效果 +# print 语法 使用 Python 2 写法 使用 print(),兼容 Python 3 +# 命名风格 AddVertex、BDFS 等不规范 使用 PEP8 标准命名:add_vertex、bdfs +# 遍历判重效率低 使用两个 for 循环在 OPEN 和 CLOSE 查找重复项 改用 set 结构做判重(visited)提升效率 +# 遍历策略混用 使用参数字符串判断 BFS/DFS,不直观 用统一函数处理模式,逻辑清晰易维护 +# 顶点添加顺序混乱 添加邻接点时引用未创建顶点会报错 确保先添加叶子节点,再添加引用它们的顶点 diff --git a/HeapSort.py b/HeapSort.py index 17e793b..016caf2 100644 --- a/HeapSort.py +++ b/HeapSort.py @@ -1,40 +1,87 @@ -import random +# import random +# # +# # +# # def MaxHeapify(A, i, s): +# # l = i * 2 +# # r = i * 2 + 1 +# # largest = i +# # if l < s and A[l] > A[i]: +# # largest = l +# # if r < s and A[r] > A[largest]: +# # largest = r +# # if largest != i: +# # A[i], A[largest] = A[largest], A[i] +# # MaxHeapify(A, largest, s) +# # +# # +# # def BuildMaxHeap(A, s): +# # for i in range(0, len(A) / 2)[::-1]: +# # MaxHeapify(A, i, s) +# # return A +# # +# # +# # def HeapSort(A): +# # s = len(A) +# # BuildMaxHeap(A, s) +# # +# # for i in range(1, len(A))[::-1]: +# # A[0], A[i] = A[i], A[0] +# # s -= 1 +# # MaxHeapify(A, 0, s) +# # return A +# # +# # +# # print "Now displaying HeapSort" +# # A = [] +# # s = random.randint(5, 100) +# # for i in range(0, s): +# # A.append(random.randint(0, 1000)) +# # print A +# # print HeapSort(A) +import random -def MaxHeapify(A, i, s): - l = i * 2 - r = i * 2 + 1 +def max_heapify(arr, i, heap_size): + """保持最大堆性质:调整以 i 为根的子树""" + left = 2 * i + 1 + right = 2 * i + 2 largest = i - if l < s and A[l] > A[i]: - largest = l - if r < s and A[r] > A[largest]: - largest = r - if largest != i: - A[i], A[largest] = A[largest], A[i] - MaxHeapify(A, largest, s) - - -def BuildMaxHeap(A, s): - for i in range(0, len(A) / 2)[::-1]: - MaxHeapify(A, i, s) - return A + if left < heap_size and arr[left] > arr[largest]: + largest = left + if right < heap_size and arr[right] > arr[largest]: + largest = right + if largest != i: + arr[i], arr[largest] = arr[largest], arr[i] + max_heapify(arr, largest, heap_size) -def HeapSort(A): - s = len(A) - BuildMaxHeap(A, s) +def build_max_heap(arr): + """从无序数组构建最大堆""" + heap_size = len(arr) + for i in range((heap_size // 2) - 1, -1, -1): + max_heapify(arr, i, heap_size) - for i in range(1, len(A))[::-1]: - A[0], A[i] = A[i], A[0] - s -= 1 - MaxHeapify(A, 0, s) - return A +def heap_sort(arr): + """堆排序主函数:升序排列数组""" + arr = arr[:] # 创建副本,避免原数组被修改(可选) + build_max_heap(arr) + heap_size = len(arr) + for i in range(len(arr) - 1, 0, -1): + arr[0], arr[i] = arr[i], arr[0] + heap_size -= 1 + max_heapify(arr, 0, heap_size) + return arr +# ==== 测试部分 ==== +print("Now displaying HeapSort") +A = [random.randint(0, 1000) for _ in range(random.randint(5, 100))] +print("Original array:", A) +sorted_array = heap_sort(A) +print("Sorted array:", sorted_array) -print "Now displaying HeapSort" -A = [] -s = random.randint(5, 100) -for i in range(0, s): - A.append(random.randint(0, 1000)) -print A -print HeapSort(A) +# 优化项 原始写法 优化后写法 +# print语法 print A print("A:", A) +# 除法运算 len(A) / 2 len(A) // 2 +# range 反向迭代 range(...)[::-1] range(..., ..., -1) +# 索引起始 l = i*2 left = 2*i + 1 +# 排序不改原数组(可选) 原地排序 拷贝后排序 diff --git a/InsertionSort.py b/InsertionSort.py index ab5781c..a0e8664 100644 --- a/InsertionSort.py +++ b/InsertionSort.py @@ -1,20 +1,48 @@ -import random +# import random +# +# +# def InsertionSort(A, n): +# for j in range(1, n): +# key = A[j] +# # Insert A[j] into the sorted sequence[1...j-1] +# i = j - 1 +# while i >= 0 and A[i] > key: +# A[i + 1] = A[i] +# i = i-1 +# A[i+1] = key +# return A +# +# A = [] +# s = random.randint(5, 100) +# for i in range(0, s): +# A.append(random.randint(0, 1000)) +# print A +# print InsertionSort(A, len(A)) +import random -def InsertionSort(A, n): - for j in range(1, n): - key = A[j] - # Insert A[j] into the sorted sequence[1...j-1] +def insertion_sort(arr): + """插入排序:升序排列列表""" + arr = arr[:] # 拷贝原数组,避免修改原始数据(可选) + for j in range(1, len(arr)): + key = arr[j] i = j - 1 - while i >= 0 and A[i] > key: - A[i + 1] = A[i] - i = i-1 - A[i+1] = key - return A + # 将 key 插入到 arr[0...j-1] 的有序子序列中 + while i >= 0 and arr[i] > key: + arr[i + 1] = arr[i] + i -= 1 + arr[i + 1] = key + return arr + +# ==== 测试部分 ==== +data = [random.randint(0, 1000) for _ in range(random.randint(5, 100))] +print("Original array:", data) +sorted_data = insertion_sort(data) +print("Sorted array: ", sorted_data) -A = [] -s = random.randint(5, 100) -for i in range(0, s): - A.append(random.randint(0, 1000)) -print A -print InsertionSort(A, len(A)) +# 优化点 原代码 优化后 +# Python 3 兼容 print A print("...", A) +# 命名规范 InsertionSort insertion_sort +# 调用简化 InsertionSort(A, len(A)) insertion_sort(A) +# 拷贝安全 修改原数组 默认拷贝,防止副作用 +# 注释明确 含糊不清 明确说明排序逻辑 diff --git a/JumpList.py b/JumpList.py index 79fe060..8a0d597 100644 --- a/JumpList.py +++ b/JumpList.py @@ -1,5 +1,96 @@ -import random +# import random +# +# +# class Node: +# def __init__(self, key, next_=None, prev=None, down=None): +# self.key = key +# self.next_ = next_ +# self.prev = prev +# self.down = down +# +# +# class List: +# def __init__(self): +# minNum, maxNum = -1, 10000 +# self.L = Node(minNum) +# E = Node(maxNum) +# self.L.next_, E.prev = E, self.L +# +# +# class JList: +# def __init__(self): +# self.JL = [] +# self.JL.append(List()) +# +# def AddLevel(self): +# self.JL.append(List()) +# self.JL[len(self.JL) - 1].L.down = self.JL[len(self.JL) - 2].L +# +# def Add(self, key): +# e = Node(key) +# i = 0 +# while random.randint(0, 9) % 2 == 0: +# i += 1 +# while len(self.JL) < i + 1: +# self.AddLevel() +# it = self.JL[i].L +# while it.key < e.key: +# it = it.next_ +# e.next_ = it +# e.prev = it.prev +# it.prev.next_ = e +# it.prev = e +# self.RecursiveAdd(e.prev.down, e, key) +# return True +# +# def RecursiveAdd(self, itt, e, key): +# if itt == None: +# return +# e.down = en = Node(key) +# while itt.key < en.key: +# itt = itt.next_ +# en.next_ = itt +# en.prev = itt.prev +# itt.prev.next_ = en +# itt.prev = en +# itt = en.prev.down +# self.RecursiveAdd(itt, en, key) +# +# def Search(self, key, Level=None): +# i = self.JL[len(self.JL) - 1].L if Level is None else Level +# while i.key < key: +# i = i.next_ +# if i.prev.down != None: +# return self.Search(key, i.prev.down) +# elif i.key == key: +# return i +# else: +# return False +# +# def Delete(self, key, Level=None): +# i = self.JL[len(self.JL) - 1].L if Level is None else Level +# while i.key < key: +# i = i.next_ +# if i.key == key: +# i.prev.next_ = i.next_ +# i.next_.prev = i.prev +# while i.down is not None: +# i = i.down +# i.prev.next_ = i.next_ +# i.next_.prev = i.prev +# elif i.prev.down != None: +# return self.Delete(key, i.prev.down) +# else: +# return False +# +# test = JList() +# for i in range(0, 10): +# test.Add(i) +# n = test.Search(6) +# for i in range(0, 1024): +# test.Delete(i) +import random class Node: def __init__(self, key, next_=None, prev=None, down=None): @@ -8,84 +99,106 @@ def __init__(self, key, next_=None, prev=None, down=None): self.prev = prev self.down = down +class LevelList: + def __init__(self): + self.head = Node(-1) + self.tail = Node(10000) + self.head.next_ = self.tail + self.tail.prev = self.head -class List: +class SkipList: def __init__(self): - minNum, maxNum = -1, 10000 - self.L = Node(minNum) - E = Node(maxNum) - self.L.next_, E.prev = E, self.L + self.levels = [] + self.levels.append(LevelList()) # Level 0 + def add_level(self): + """新增一层并连接上一层""" + new_level = LevelList() + new_level.head.down = self.levels[-1].head + self.levels.append(new_level) -class JList: - def __init__(self): - self.JL = [] - self.JL.append(List()) - - def AddLevel(self): - self.JL.append(List()) - self.JL[len(self.JL) - 1].L.down = self.JL[len(self.JL) - 2].L - - def Add(self, key): - e = Node(key) - i = 0 - while random.randint(0, 9) % 2 == 0: - i += 1 - while len(self.JL) < i + 1: - self.AddLevel() - it = self.JL[i].L - while it.key < e.key: - it = it.next_ - e.next_ = it - e.prev = it.prev - it.prev.next_ = e - it.prev = e - self.RecursiveAdd(e.prev.down, e, key) - return True - - def RecursiveAdd(self, itt, e, key): - if itt == None: + def insert(self, key): + level = 0 + # 随机决定插入的层数 + while random.randint(0, 1) == 0: + level += 1 + while len(self.levels) <= level: + self.add_level() + + new_node = Node(key) + current = self.levels[level].head + + # 寻找插入位置 + while current.key < key: + current = current.next_ + # 插入节点 + new_node.next_ = current + new_node.prev = current.prev + current.prev.next_ = new_node + current.prev = new_node + + # 向下递归插入 + self._insert_down(new_node, new_node.prev.down, key) + + def _insert_down(self, upper_node, down_node, key): + if down_node is None: return - e.down = en = Node(key) - while itt.key < en.key: - itt = itt.next_ - en.next_ = itt - en.prev = itt.prev - itt.prev.next_ = en - itt.prev = en - itt = en.prev.down - self.RecursiveAdd(itt, en, key) - - def Search(self, key, Level=None): - i = self.JL[len(self.JL) - 1].L if Level is None else Level - while i.key < key: - i = i.next_ - if i.prev.down != None: - return self.Search(key, i.prev.down) - elif i.key == key: - return i - else: - return False - - def Delete(self, key, Level=None): - i = self.JL[len(self.JL) - 1].L if Level is None else Level - while i.key < key: - i = i.next_ - if i.key == key: - i.prev.next_ = i.next_ - i.next_.prev = i.prev - while i.down is not None: - i = i.down - i.prev.next_ = i.next_ - i.next_.prev = i.prev - elif i.prev.down != None: - return self.Delete(key, i.prev.down) - else: - return False - -test = JList() -for i in range(0, 10): - test.Add(i) -n = test.Search(6) -for i in range(0, 1024): - test.Delete(i) + # 向下插入 + new_node = Node(key) + upper_node.down = new_node + + current = down_node + while current.key < key: + current = current.next_ + new_node.next_ = current + new_node.prev = current.prev + current.prev.next_ = new_node + current.prev = new_node + + self._insert_down(new_node, new_node.prev.down, key) + + def search(self, key): + current = self.levels[-1].head + while current: + while current.next_ and current.next_.key <= key: + current = current.next_ + if current.key == key: + return current + current = current.down + return None + + def delete(self, key): + current = self.levels[-1].head + found = False + while current: + while current.next_ and current.next_.key < key: + current = current.next_ + if current.next_ and current.next_.key == key: + target = current.next_ + current.next_ = target.next_ + target.next_.prev = current + found = True + current = current.down + else: + current = current.down + return found + +# ==== 测试 ==== +if __name__ == "__main__": + skiplist = SkipList() + for i in range(10): + skiplist.insert(i) + + node = skiplist.search(6) + print("Found 6" if node else "6 Not Found") + + for i in range(1024): + skiplist.delete(i) + print("Deletion done.") + +# 项目 优化前 优化后 +# 命名规范 List 与 Python 保留字冲突 改为 LevelList,避免冲突 +# 层间链接 手动链接复杂 结构清晰,head.down 链接上下层 +# 插入流程 多层嵌套 _insert_down 封装递归逻辑 +# 删除流程 缺乏状态返回 返回布尔值说明是否成功删除 +# 结构健壮性 无断链保护,逻辑易错 添加空值判断与边界保护 diff --git a/LongestCommonSubsequence.py b/LongestCommonSubsequence.py index 5e0a8d7..8796022 100644 --- a/LongestCommonSubsequence.py +++ b/LongestCommonSubsequence.py @@ -1,28 +1,72 @@ -def LCSString(b, X, i, j): - if i == -1 or j == -1: - return - if b[i][j] == "SLOPE": - a = LCSString(b, X, i - 1, j - 1) - return X[i] if a is None else a + X[i] - elif b[i][j] == "UP": - return LCSString(b, X, i - 1, j) +# def LCSString(b, X, i, j): +# if i == -1 or j == -1: +# return +# if b[i][j] == "SLOPE": +# a = LCSString(b, X, i - 1, j - 1) +# return X[i] if a is None else a + X[i] +# elif b[i][j] == "UP": +# return LCSString(b, X, i - 1, j) +# else: +# return LCSString(b, X, i, j - 1) +# +# def LCS(X, Y): +# b = [[0 for i in range(0, len(Y))] for i in range(0, len(X))] +# c = [[0 for i in range(0, len(Y) + 1)] for i in range(0, len(X) + 1)] +# for i in range(0, len(X)): +# for j in range(0, len(Y)): +# if X[i] == Y[j]: +# c[i + 1][j + 1] = c[i][j] + 1 +# b[i][j] = "SLOPE" +# elif c[i][j + 1] > c[i + 1][j]: +# c[i + 1][j + 1] = c[i][j + 1] +# b[i][j] = "UP" +# else: +# c[i + 1][j + 1] = c[i + 1][j] +# b[i][j] = "LEFT" +# return LCSString(b, X, len(X) - 1, len(Y) - 1) +# +# print LCS("ABCBDAB", "BDCABA") +def lcs_string(trace, X, i, j): + """根据方向表 trace 回溯得到 LCS 字符串""" + if i < 0 or j < 0: + return "" + if trace[i][j] == "SLOPE": + return lcs_string(trace, X, i - 1, j - 1) + X[i] + elif trace[i][j] == "UP": + return lcs_string(trace, X, i - 1, j) else: - return LCSString(b, X, i, j - 1) + return lcs_string(trace, X, i, j - 1) -def LCS(X, Y): - b = [[0 for i in range(0, len(Y))] for i in range(0, len(X))] - c = [[0 for i in range(0, len(Y) + 1)] for i in range(0, len(X) + 1)] - for i in range(0, len(X)): - for j in range(0, len(Y)): +def lcs(X, Y): + """计算 X 与 Y 的最长公共子序列""" + m, n = len(X), len(Y) + # 动态规划表和方向表 + dp = [[0] * (n + 1) for _ in range(m + 1)] + trace = [[""] * n for _ in range(m)] + + # 填表 + for i in range(m): + for j in range(n): if X[i] == Y[j]: - c[i + 1][j + 1] = c[i][j] + 1 - b[i][j] = "SLOPE" - elif c[i][j + 1] > c[i + 1][j]: - c[i + 1][j + 1] = c[i][j + 1] - b[i][j] = "UP" + dp[i + 1][j + 1] = dp[i][j] + 1 + trace[i][j] = "SLOPE" + elif dp[i][j + 1] > dp[i + 1][j]: + dp[i + 1][j + 1] = dp[i][j + 1] + trace[i][j] = "UP" else: - c[i + 1][j + 1] = c[i + 1][j] - b[i][j] = "LEFT" - return LCSString(b, X, len(X) - 1, len(Y) - 1) + dp[i + 1][j + 1] = dp[i + 1][j] + trace[i][j] = "LEFT" + + return lcs_string(trace, X, m - 1, n - 1) + +# ==== 测试 ==== +print(lcs("ABCBDAB", "BDCABA")) # 输出应为 "BCBA" 或 "BDAB" + + -print LCS("ABCBDAB", "BDCABA") +# 项目 优化内容 +# Python 3 兼容 使用 print() 函数 +# 命名标准 遵循 PEP 8,函数名小写,变量有意义 +# 输出逻辑明确 LCSString() 返回字符串,避免 None 拼接错误 +# 边界处理更清晰 初始条件明确(索引从 1 开始) +# 添加注释 每步加解释,便于理解动态规划过程 From 65f4dcef2f4a44ab845b570664840e7f0e82c4c5 Mon Sep 17 00:00:00 2001 From: Shiyang Liu <141719831+CodingNoFuture@users.noreply.github.com> Date: Mon, 12 May 2025 20:47:23 +0800 Subject: [PATCH 04/17] Shiyang Update Shiyang Update for a half part of code --- MergeSort.py | 73 ++++++----- MiddleSelect.py | 94 +++++--------- OpenAddressingHash.py | 53 ++++---- PowerProblem.py | 34 +++-- Queue.py | 33 +++++ QuickSort.py | 41 +++--- RadixSort.py | 48 +++----- RandomizedSelect.py | 55 ++++----- RedBlackTree.py | 281 +++++++++++++----------------------------- Stack.py | 53 +++----- 10 files changed, 310 insertions(+), 455 deletions(-) create mode 100644 Queue.py diff --git a/MergeSort.py b/MergeSort.py index 20d3808..c6f83c2 100644 --- a/MergeSort.py +++ b/MergeSort.py @@ -1,43 +1,42 @@ import random - -def MergeSort(A, p, r): - q = (p + r) / 2 # Find the middle - if p < r: - MergeSort(A, p, q) # MergeSort A[p...q] - MergeSort(A, q + 1, r) # MergeSort A[p+1....r] - return Merge(A, p, q, r) - - -# The guard in Merge() -MAX = 10000 - - -def Merge(A, p, q, r): - L = [] - R = [] - for i in range(p, q + 1): # Copy the left side. - L.append(A[i]) - for i in range(q + 1, r + 1): # Copy the right side. - R.append(A[i]) - L.append(MAX) # Add guard to the end. - R.append(MAX) # Add guard to the end. - i = 0 - j = 0 - for k in range(p, r + 1): - if L[i] < R[j]: +def merge_sort(A): + def merge_sort_recursive(A, p, r): + if p < r: + q = (p + r) // 2 + merge_sort_recursive(A, p, q) + merge_sort_recursive(A, q + 1, r) + merge(A, p, q, r) + + def merge(A, p, q, r): + L = A[p:q+1] + R = A[q+1:r+1] + i = j = 0 + k = p + + while i < len(L) and j < len(R): + if L[i] <= R[j]: + A[k] = L[i] + i += 1 + else: + A[k] = R[j] + j += 1 + k += 1 + + while i < len(L): A[k] = L[i] - i = i + 1 - else: + i += 1 + k += 1 + while j < len(R): A[k] = R[j] - j = j + 1 - return A + j += 1 + k += 1 + merge_sort_recursive(A, 0, len(A) - 1) -print "Now displaying MergeSort" -A = [] -s = random.randint(5, 100) -for i in range(0, s): - A.append(random.randint(0, 1000)) -print A -print MergeSort(A, 0, len(A) - 1) +if __name__ == "__main__": + print("Now displaying MergeSort") + A = [random.randint(0, 1000) for _ in range(random.randint(5, 100))] + print("Before:", A) + merge_sort(A) + print("After:", A) \ No newline at end of file diff --git a/MiddleSelect.py b/MiddleSelect.py index d47cd0c..f38174e 100644 --- a/MiddleSelect.py +++ b/MiddleSelect.py @@ -1,63 +1,35 @@ import random - -def Partition(A, p, r): - x = A[p] # To get a randomized elem. - i = p - 1 - for j in range(p, r + 1): - if A[j] <= x: - i += 1 - A[i], A[j] = A[j], A[i] - A[p], A[i] = A[i], A[p] - return i - - -def QuickSort(A, p, r): - if r > p: - q = Partition(A, p, r) - QuickSort(A, p, q - 1) - QuickSort(A, q + 1, r) - return A - - -def MiddlePartition(A, p, r): - # To get the middle of the elem. - T = [[A[i] for i in range(j * 5, j * 5 + 5)] for j in range(0, (0 + len(A)) / 5)] - m = [] - for i in T: - QuickSort(i, 0, 4) - m.append(i[2]) - QuickSort(m, 0, len(m) - 1) - mm = m[len(m) / 2] - - x = mm - i = p - 1 - for j in range(p, r + 1): - if A[j] <= x: - i += 1 - A[i], A[j] = A[j], A[i] - A[p], A[i] = A[i], A[p] - return i - - -def MiddleSelect(A, p, r, i): - if p == r: - return A[p] - q = MiddlePartition(A, p, r) - if q == i: - return A[q] - if q > i: - return MiddleSelect(A, p, q - 1, i) - if q < i: - return MiddleSelect(A, q + 1, r, i) - - -print "Now displaying Middle Select" -A = [] -s = random.randint(5, 100) -for i in range(0, s): - A.append(random.randint(0, 1000)) -print A -i = random.randint(0, s) -print "The position of ", i, "is :", MiddleSelect(A, 0, len(A) - 1, i) - +def quicksort(arr): + if len(arr) <= 1: + return arr + pivot = arr[random.randint(0, len(arr) - 1)] + left = [x for x in arr if x < pivot] + mid = [x for x in arr if x == pivot] + right = [x for x in arr if x > pivot] + return quicksort(left) + mid + quicksort(right) + +def middle_select(A, i): + def select(arr, k): + if len(arr) <= 5: + return sorted(arr)[k] + chunks = [arr[j:j+5] for j in range(0, len(arr), 5)] + medians = [sorted(chunk)[len(chunk)//2] for chunk in chunks] + pivot = select(medians, len(medians)//2) + low = [x for x in arr if x < pivot] + high = [x for x in arr if x > pivot] + count = arr.count(pivot) + if k < len(low): + return select(low, k) + elif k < len(low) + count: + return pivot + else: + return select(high, k - len(low) - count) + return select(A, i) + +if __name__ == "__main__": + print("Now displaying Middle Select") + A = [random.randint(0, 1000) for _ in range(random.randint(5, 100))] + print("Array:", A) + i = random.randint(0, len(A) - 1) + print(f"The {i}-th smallest element is:", middle_select(A, i)) \ No newline at end of file diff --git a/OpenAddressingHash.py b/OpenAddressingHash.py index 22fe9ac..7cc4105 100644 --- a/OpenAddressingHash.py +++ b/OpenAddressingHash.py @@ -1,31 +1,32 @@ import random +class OpenAddressingHash: + def __init__(self, size): + self.size = size + self.table = [-1] * size -def HashInsert(e, T, s): - for i in range(0, s): - if T[(e + i) % s] == -1: - T[(e + i) % s] = e - return True - return False + def insert(self, key): + for i in range(self.size): + idx = (key + i) % self.size + if self.table[idx] == -1: + self.table[idx] = key + return True + return False + def search(self, key): + for i in range(self.size): + idx = (key + i) % self.size + if self.table[idx] == key: + return idx + return -1 -def HashSearch(e, T, s): - for i in range(0, s): - if T[(e + i) % s] == e: - return (e + i) % s - return False - - -print "Now displaying Open Addressing Hash." -s = 13 -A = [] -T = [-1 for i in range(0, s)] -t = random.randint(5, 100) -for i in range(0, t): - A.append(random.randint(0, 1000)) -for e in A: - HashInsert(e, T, s) -print T -e = random.choice(A) -i = HashSearch(e, T, s) -print "The selected elem ", e, " is in Slot:", i +if __name__ == "__main__": + print("Now displaying Open Addressing Hash.") + size = 13 + oah = OpenAddressingHash(size) + A = [random.randint(0, 1000) for _ in range(random.randint(5, 20))] + for e in A: + oah.insert(e) + print("Hash table:", oah.table) + e = random.choice(A) + print(f"The selected element {e} is in slot:", oah.search(e)) \ No newline at end of file diff --git a/PowerProblem.py b/PowerProblem.py index 608b99f..e3ec8a3 100644 --- a/PowerProblem.py +++ b/PowerProblem.py @@ -1,23 +1,17 @@ import random +def fast_pow(x, n): + result = 1 + base = x + while n > 0: + if n % 2 == 1: + result *= base + base *= base + n //= 2 + return result -def MyPow(x, n): - if n == 0: - return 1 - if n == 1: - return x - if n == 2: - return x * x - if n % 2 == 0: - return MyPow(MyPow(x, n / 2), 2) - if n % 2 == 1: - return MyPow(MyPow(x, n / 2), 2) * x - - -print "Now Displaying PowerProblem." -x = random.randint(4, 999) -n = random.randint(3, 40) -print x, " powers ", n -# x = 1 -# n = 2 -print MyPow(x, n), " comparing to build_in function: ", pow(x, n) +if __name__ == "__main__": + print("Now displaying PowerProblem.") + x = random.randint(4, 999) + n = random.randint(3, 40) + print(f"{x} to the power {n} is: {fast_pow(x, n)}, comparing to built-in: {pow(x, n)}") \ No newline at end of file diff --git a/Queue.py b/Queue.py new file mode 100644 index 0000000..5e89f12 --- /dev/null +++ b/Queue.py @@ -0,0 +1,33 @@ +class CircularQueue: + def __init__(self, size=10): + self.size = size + self.queue = [None] * size + self.head = 0 + self.tail = 0 + + def is_empty(self): + return self.head == self.tail + + def is_full(self): + return (self.tail + 1) % self.size == self.head + + def enqueue(self, value): + if self.is_full(): + return False + self.queue[self.tail] = value + self.tail = (self.tail + 1) % self.size + return True + + def dequeue(self): + if self.is_empty(): + return None + val = self.queue[self.head] + self.head = (self.head + 1) % self.size + return val + +if __name__ == "__main__": + q = CircularQueue() + for i in range(9): # Only size - 1 elements allowed + q.enqueue(i) + while not q.is_empty(): + print(q.dequeue()) \ No newline at end of file diff --git a/QuickSort.py b/QuickSort.py index 947049d..d01c94e 100644 --- a/QuickSort.py +++ b/QuickSort.py @@ -1,31 +1,26 @@ import random +def quicksort(A, p, r): + if p < r: + q = partition(A, p, r) + quicksort(A, p, q - 1) + quicksort(A, q + 1, r) -def Partition(A, p, r): - it = random.randint(p, r) # To get a randomized elem. - A[p], A[it] = A[it], A[p] - x = A[p] - i = p - 1 - for j in range(p, r + 1): - if A[j] <= x: +def partition(A, p, r): + pivot_index = random.randint(p, r) + A[p], A[pivot_index] = A[pivot_index], A[p] + pivot = A[p] + i = p + for j in range(p + 1, r + 1): + if A[j] < pivot: i += 1 A[i], A[j] = A[j], A[i] A[p], A[i] = A[i], A[p] return i - -def QuickSort(A, p, r): - if r > p: - q = Partition(A, p, r) - QuickSort(A, p, q - 1) - QuickSort(A, q + 1, r) - return A - - -print "Now displaying QuickSort" -A = [] -s = random.randint(5, 100) -for i in range(0, s): - A.append(random.randint(0, 1000)) -print A -print QuickSort(A, 0, len(A) - 1) +if __name__ == "__main__": + print("Now displaying QuickSort") + A = [random.randint(0, 1000) for _ in range(random.randint(5, 100))] + print("Before:", A) + quicksort(A, 0, len(A) - 1) + print("After:", A) \ No newline at end of file diff --git a/RadixSort.py b/RadixSort.py index 6065532..88148b1 100644 --- a/RadixSort.py +++ b/RadixSort.py @@ -1,31 +1,19 @@ import random - - -def GetI(n): - i = 0 - while n != 0: - n /= 10 - i += 1 - return i - - -def GetKey(n, i): - ret = n - ret /= pow(10, i) - return ret % 10 - - -def RadixSort(A): - for i in range(0, GetI(A[0])): - A.sort(lambda x, y: cmp(GetKey(x, i), GetKey(y, i))) - return A - - -print "Now displaying Radix Sort." -A = [] -s = random.randint(4, 100) -for i in range(0, s): - A.append(random.randint(0, 999)) -print A -print RadixSort(A) -print "DEBUG" +from collections import defaultdict + +def radix_sort(arr): + max_len = len(str(max(arr))) + for i in range(max_len): + buckets = [[] for _ in range(10)] + for num in arr: + digit = (num // (10 ** i)) % 10 + buckets[digit].append(num) + arr = [num for bucket in buckets for num in bucket] + return arr + +if __name__ == "__main__": + print("Now displaying Radix Sort.") + A = [random.randint(0, 999) for _ in range(random.randint(4, 100))] + print("Before:", A) + A = radix_sort(A) + print("After:", A) \ No newline at end of file diff --git a/RandomizedSelect.py b/RandomizedSelect.py index 1378d25..4789483 100644 --- a/RandomizedSelect.py +++ b/RandomizedSelect.py @@ -1,38 +1,33 @@ import random +def randomized_select(A, p, r, i): + if p == r: + return A[p] + q = randomized_partition(A, p, r) + k = q - p + if i == k: + return A[q] + elif i < k: + return randomized_select(A, p, q - 1, i) + else: + return randomized_select(A, q + 1, r, i - k - 1) -def RandomizedPartition(A, p, r): - it = random.randint(p, r) - A[p], A[it] = A[it], A[p] - x = A[p] # To get a randomized elem. - i = p - 1 - for j in range(p, r + 1): - if A[j] <= x: +def randomized_partition(A, p, r): + pivot_index = random.randint(p, r) + A[p], A[pivot_index] = A[pivot_index], A[p] + pivot = A[p] + i = p + for j in range(p + 1, r + 1): + if A[j] < pivot: i += 1 A[i], A[j] = A[j], A[i] A[p], A[i] = A[i], A[p] return i - -def RandomizedSelect(A, p, r, i): - # if p == r: - # return A[p] - q = RandomizedPartition(A, p, r) - if q == i: - return A[q] - if q > i: - return RandomizedSelect(A, p, q - 1, i) - if q < i: - return RandomizedSelect(A, q + 1, r, i) - - -print "Now displaying Randomized Select" -A = [] -s = random.randint(5, 100000) -for i in range(0, s): - A.append(random.randint(0, 100000000)) -# print A -i = random.randint(0, s - 1) -print "The position of ", i, "is :", RandomizedSelect(A, 0, len(A) - 1, i) -A.sort() -print A[i] +if __name__ == "__main__": + print("Now displaying Randomized Select") + A = [random.randint(0, 100000000) for _ in range(random.randint(5, 100))] + idx = random.randint(0, len(A) - 1) + result = randomized_select(A, 0, len(A) - 1, idx) + print(f"The {idx}-th smallest element is:", result) + print("Correct (sorted):", sorted(A)[idx]) \ No newline at end of file diff --git a/RedBlackTree.py b/RedBlackTree.py index c1d8851..f27653e 100644 --- a/RedBlackTree.py +++ b/RedBlackTree.py @@ -1,218 +1,109 @@ class Node: - def __init__(self, key, left=None, right=None, color=None, p=None): + def __init__(self, key, color='RED', left=None, right=None, parent=None): + self.key = key + self.color = color self.left = left self.right = right - self.color = color - self.key = key - self.p = p - if key == "NIL": - self.p = self + self.parent = parent + +class RedBlackTree: + def __init__(self): + self.NIL = Node(None, color='BLACK') + self.root = self.NIL - def LeftRotate(self, T, x): + def left_rotate(self, x): y = x.right x.right = y.left - if y.left != T.nil: - y.left.p = x - y.p = x.p - if x.p == T.nil: - T.root = y - elif x == x.p.left: - x.p.left = y + if y.left != self.NIL: + y.left.parent = x + y.parent = x.parent + if x.parent == self.NIL: + self.root = y + elif x == x.parent.left: + x.parent.left = y else: - x.p.right = y + x.parent.right = y y.left = x - x.p = y + x.parent = y - def RightRotate(self, T, x): + def right_rotate(self, x): y = x.left x.left = y.right - if y.right != T.nil: - y.right.p = x - y.p = x.p - if x.p == T.nil: - T.root = y - elif x == x.p.left: - x.p.left = y + if y.right != self.NIL: + y.right.parent = x + y.parent = x.parent + if x.parent == self.NIL: + self.root = y + elif x == x.parent.right: + x.parent.right = y else: - x.p.right = y + x.parent.left = y y.right = x - x.p = y + x.parent = y - def RBInsert(self, T, z): - y = T.nil - x = T.root - while x != T.nil: + def insert(self, key): + node = Node(key, left=self.NIL, right=self.NIL, parent=None) + y = self.NIL + x = self.root + while x != self.NIL: y = x - if z.key < x.key: + if node.key < x.key: x = x.left else: x = x.right - z.p = y - if y == T.nil: - T.root = z - elif z.key < y.key: - y.left = z - else: - y.right = z - z.left = T.nil - z.right = T.nil - z.color = "RED" - self.RBInsertFixUp(T, z) - - def TreeHeight(self, T, z): - if z == T.nil: - return 0 - lh = self.TreeHeight(T, z.left) - rh = self.TreeHeight(T, z.right) - if lh > rh: - return lh + 1 - return rh + 1 - - def RBInsertFixUp(self, T, z): - while z.p.color == "RED": - if z.p == z.p.p.left: - y = z.p.p.right - if y.color == "RED": - z.p.color = "BLACK" - y.color = "BLACK" - z.p.p.color = "RED" - z = z.p.p - elif z == z.p.right: - z = z.p - self.LeftRotate(T, z) - z.p.color = "BLACK" - if z.p.p != T.nil: - z.p.p.color = "RED" - self.RightRotate(T, z.p.p) - else: - y = z.p.p.left - if y.color == "RED": - z.p.color = "BLACK" - y.color = "BLACK" - z.p.p.color = "RED" - z = z.p.p - elif z == z.p.left: - z = z.p - self.RightRotate(T, z) - z.p.color = "BLACK" - if z.p.p != T.nil: - z.p.p.color = "RED" - self.LeftRotate(T, z.p.p) - T.root.color = "BLACK" - - def RBTransplant(self, T, u, v): - if u.p == T.nil: - T.root = v - elif u == u.p.left: - u.p.left = v - else: - u.p.right = v - v.p = u.p - - def TreeMinimum(self, T, z): - if z.left != T.nil: - return self.TreeMinimum(T, z.left) + node.parent = y + if y == self.NIL: + self.root = node + elif node.key < y.key: + y.left = node else: - return z - - def RBDeleteFixUp(self, T, x): - while x != T.root and x.color == "BLACK": - if x == x.p.left: - w = x.p.right - if w.color == "RED": - w.color = "BLACK" - x.p.color = "RED" - self.LeftRotate(T, x.p) - w = x.p.right - if w !=T.nil : - if w.left.color == "BLACK" and w.right.color == "BLACK": - w.color = "RED" - x = x.p - elif w.right.color == "BLACK": - w.left.color = "BLACK" - w.color = "RED" - self.RightRotate(T, w) - w = x.p.right - w.color = x.p.color - x.p.color = "BLACK" - w.right.color = "BLACK" - self.LeftRotate(T, x.p) - x = T.root - else: - w = x.p.left - if w.color == "RED": - w.color = "BLACK" - x.p.color = "RED" - self.RightRotate(T, x.p) - w = x.p.left - if w.right.color == "BLACK" and w.left.color == "BLACK": - w.color = "RED" - x = x.p - elif w.left.color == "BLACK": - w.right.color = "BLACK" - w.color = "RED" - self.LeftRotate(T, w) - w = x.p.left - w.color = x.p.color - x.p.color = "BLACK" - w.left.color = "BLACK" - self.RightRotate(T, x.p) - x = T.root - x.color = "BLACK" + y.right = node + node.color = 'RED' + self.fix_insert(node) - def RBDelete(self, T, z): - y = z - yOriginalColor = y.color - if z.left == T.nil: - x = z.right - self.RBTransplant(T, z, z.right) - elif z.right == T.nil: - x = z.left - self.RBTransplant(T, z, z.left) - else: - y = self.TreeMinimum(T, z.right) - yOriginalColor = y.color - x = y.right - if y.p == z: - x.p = y + def fix_insert(self, z): + while z.parent.color == 'RED': + if z.parent == z.parent.parent.left: + y = z.parent.parent.right + if y.color == 'RED': + z.parent.color = 'BLACK' + y.color = 'BLACK' + z.parent.parent.color = 'RED' + z = z.parent.parent + else: + if z == z.parent.right: + z = z.parent + self.left_rotate(z) + z.parent.color = 'BLACK' + z.parent.parent.color = 'RED' + self.right_rotate(z.parent.parent) else: - self.RBTransplant(T, y, y.right) - y.right = z.right - y.right.p = y - self.RBTransplant(T, z, y) - y.left = z.left - y.left.p = y - y.color = z.color - if yOriginalColor == "BLACK": - self.RBDeleteFixUp(T, x) - - def InOrderTraversal(self, T, s, A): - if s == T.nil : - return - if s.left != T.nil: - self.InOrderTraversal(T, s.left, A) - A.append(s) - if s.right != T.nil: - self.InOrderTraversal(T, s.right, A) - - -class Tree: - def __init__(self): - nil = Node("NIL", color="BLACK") - self.root = nil - self.nil = nil + y = z.parent.parent.left + if y.color == 'RED': + z.parent.color = 'BLACK' + y.color = 'BLACK' + z.parent.parent.color = 'RED' + z = z.parent.parent + else: + if z == z.parent.left: + z = z.parent + self.right_rotate(z) + z.parent.color = 'BLACK' + z.parent.parent.color = 'RED' + self.left_rotate(z.parent.parent) + self.root.color = 'BLACK' + def inorder(self, node): + if node != self.NIL: + self.inorder(node.left) + print(f"{node.key}({node.color})", end=' ') + self.inorder(node.right) -T = Tree() -B = [11, 2, 14, 1, 7, 15, 5, 8, 4] -BB = [26] -for j in B: - T.root.RBInsert(T, Node(j)) - print j -A = [] -T.root.InOrderTraversal(T, T.root, A) -for i in A: - T.root.RBDelete(T, i) - AA = [] - T.root.InOrderTraversal(T, T.root, AA) - print "AfterDeleting ", i.key, ".Nodes in tree:", [AAA.key for AAA in AA] +if __name__ == "__main__": + tree = RedBlackTree() + keys = [11, 2, 14, 1, 7, 15, 5, 8, 4] + for k in keys: + tree.insert(k) + print("Inorder traversal of Red-Black Tree:") + tree.inorder(tree.root) + print() \ No newline at end of file diff --git a/Stack.py b/Stack.py index 827b18d..ea66d48 100644 --- a/Stack.py +++ b/Stack.py @@ -1,35 +1,22 @@ -import random - - class Stack: def __init__(self): - self.top = -1 - self.s = 100 - self.S = [0 for i in range(0, self.s)] - - def StackEmpty(self): - if self.top == -1: - return True - return False - - def Push(self, x): - if self.top == self.s - 1: - return False - self.top += 1 - self.S[self.top] = x - return True - - def Pop(self): - if self.StackEmpty(): - return False - else: - self.top -= 1 - return self.S[self.top + 1] - - -S = Stack() -for i in range(0, 120): - S.Push(random.randint(0,999)) - -while not S.StackEmpty(): - print S.Pop() + self.stack = [] + + def is_empty(self): + return len(self.stack) == 0 + + def push(self, item): + self.stack.append(item) + + def pop(self): + if self.is_empty(): + return None + return self.stack.pop() + +if __name__ == "__main__": + import random + s = Stack() + for _ in range(20): + s.push(random.randint(0, 999)) + while not s.is_empty(): + print(s.pop()) \ No newline at end of file From 711468c82e99522fd6a514afa43afdde04a85976 Mon Sep 17 00:00:00 2001 From: Abang111 Date: Mon, 12 May 2025 21:00:09 +0800 Subject: [PATCH 05/17] add more code --- .idea/IntroductionToAlgorithms.iml | 11 ----- .idea/inspectionProfiles/Project_Default.xml | 12 ------ .../inspectionProfiles/profiles_settings.xml | 7 ---- .idea/misc.xml | 4 -- .idea/modules.xml | 8 ---- .idea/vcs.xml | 6 --- Queue_.py | 42 ------------------- 7 files changed, 90 deletions(-) delete mode 100644 .idea/IntroductionToAlgorithms.iml delete mode 100644 .idea/inspectionProfiles/Project_Default.xml delete mode 100644 .idea/inspectionProfiles/profiles_settings.xml delete mode 100644 .idea/misc.xml delete mode 100644 .idea/modules.xml delete mode 100644 .idea/vcs.xml delete mode 100644 Queue_.py diff --git a/.idea/IntroductionToAlgorithms.iml b/.idea/IntroductionToAlgorithms.iml deleted file mode 100644 index be97450..0000000 --- a/.idea/IntroductionToAlgorithms.iml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml deleted file mode 100644 index 06bb031..0000000 --- a/.idea/inspectionProfiles/Project_Default.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml deleted file mode 100644 index 3b31283..0000000 --- a/.idea/inspectionProfiles/profiles_settings.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 0cdfdaa..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index db86a73..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/Queue_.py b/Queue_.py deleted file mode 100644 index 02b9478..0000000 --- a/Queue_.py +++ /dev/null @@ -1,42 +0,0 @@ -class Queue_(): - def __init__(self, length=10): - self.head = 0 - self.tail = 1 - self.length = length - self.Q = [0 for i in range(self.length)] - # Actually there are only length-1 spaces in Q. - # And we need to leave one space to determine whether fullStack or emptyStack. - # So the available space is length - 2 - - def QueueEmpty(self): - if (self.head + 1) % self.length == self.tail: - return True - return False - - def QueueFull(self): - if (self.tail + 1) % self.length == self.head: - return True - return False - - def Enqueue(self, x): - if self.QueueFull(): - return False - else: - self.Q[self.tail] = x - self.tail = (self.tail + 1) % self.length - return True - - def Dequeue(self): - if self.QueueEmpty(): - return None - else: - self.head += 1 - return self.Q[self.head] - - -Q = Queue_() -for i in range(0, 10): - Q.Enqueue(i) - -while not Q.QueueEmpty(): - print Q.Dequeue() From 1f71ec2c09c3ca2d0da2380b37fa7c0c3f906a1a Mon Sep 17 00:00:00 2001 From: Abang111 Date: Mon, 12 May 2025 21:03:21 +0800 Subject: [PATCH 06/17] more folder --- C++/add all code in C.txt | 0 C++/code with C++.txt | 0 JAVA/add code in java.txt | 0 JAVA/code for java.txt | 0 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 C++/add all code in C.txt create mode 100644 C++/code with C++.txt create mode 100644 JAVA/add code in java.txt create mode 100644 JAVA/code for java.txt diff --git a/C++/add all code in C.txt b/C++/add all code in C.txt new file mode 100644 index 0000000..e69de29 diff --git a/C++/code with C++.txt b/C++/code with C++.txt new file mode 100644 index 0000000..e69de29 diff --git a/JAVA/add code in java.txt b/JAVA/add code in java.txt new file mode 100644 index 0000000..e69de29 diff --git a/JAVA/code for java.txt b/JAVA/code for java.txt new file mode 100644 index 0000000..e69de29 From 15fae579894b6a341271c9e79b247dcb89958d20 Mon Sep 17 00:00:00 2001 From: Abang111 Date: Tue, 13 May 2025 17:56:14 +0800 Subject: [PATCH 07/17] changelog --- CHANGELOG.md | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..4b3fe6c --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,41 @@ +# Changelog + + +## [1.0.0] - 2025-05-05 + +### Added +- Introduced `CHANGELOG.md` for tracking updates. +- Added structured test cases to all files for demonstration. +- Included display and debug output in all modules. + +### Changed + +#### BinarySearch.py +- Converted all `print` statements to Python 3 format. +- Fixed bug in binary search: changed `q = (p + r) / 2` to integer division. +- Added type annotations and modularized functions. +- Improved edge condition logic in binary search. + +#### BinarySearchTree.py +- Refactored with `TreeNode` and `BinarySearchTree` classes for better OOP structure. +- Fixed bug in root transplant logic. +- Enhanced output clarity and added deletion verification. +- Prepared structure for future AVL tree support. + +#### ChainingHash.py +- Changed all `print` to Python 3 syntax. +- Improved variable naming (`A`, `T`, `s` → `data`, `hash_table`, `slot_size`). +- Added docstrings to all functions. +- Added check before deletion to avoid exceptions. + +#### Dijkstra.py +- Rewrote class structure to separate `Vertex` and `Graph` clearly. +- Renamed methods to follow PEP 8 (`add_vertex`, `add_edge`, etc.). +- Removed deprecated `cmp` usage; used `sort(key=lambda x: x[1])` instead. +- Refactored Dijkstra’s logic into `dijkstra()` and `_recursion()` for clarity. + +#### DoubleLinkedList.py +- Changed `ListInsert`, `ListDelete`, etc., to PEP 8-compliant names. +- Replaced print with formatted `print()` functions. +- Added a `display()` method for full list traversal. +- Prevented deletion of sentinel `NIL` node with warning output. \ No newline at end of file From c37c87bb21ebcb243a906754b181a1221afccfde Mon Sep 17 00:00:00 2001 From: Abang111 Date: Tue, 13 May 2025 18:01:50 +0800 Subject: [PATCH 08/17] changelog in May07 --- CHANGELOG.md | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b3fe6c..d9d1a6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,42 @@ # Changelog +## [1.0.1] - 2025-05-06 + +### Changed + +#### HeapSort.py +- Replaced Python 2-style division `/` with integer division `//` for index calculation. +- Converted reverse loop slicing to `range(..., ..., -1)` for clarity and efficiency. +- Updated `heap_sort()` to return a copy of the array, preserving the original. +- Improved variable names and added inline documentation for heap operations. + +#### InsertionSort.py +- Renamed `InsertionSort` to `insertion_sort` to follow PEP8 naming conventions. +- Replaced `print` statements with Python 3-compatible `print()` functions. +- Sorting logic updated to avoid in-place mutation by returning a new list. +- Enhanced readability with concise inline comments. + +#### JumpList.py +- Renamed classes: `List` → `LevelList`, `JList` → `SkipList` to avoid naming conflicts and improve clarity. +- Refactored multi-level node insertion into a helper method `_insert_down`. +- Added boolean return value to deletion method for clearer success indication. +- Strengthened `down` pointer logic to ensure correct multi-level linking. + +#### FibonacciNumber.py +- Renamed functions using snake_case: `naive_fibonacci`, `linear_fibonacci`, `logarithmic_fibonacci`. +- Used integer division `//` to fix potential indexing issues in matrix exponentiation. +- Added explicit handling for edge cases like `n=0` for numerical stability. +- Organized and preserved all three implementations for comparison and benchmarking. + +#### Graph_BFS&DFS.py +- Renamed methods and variables (e.g., `AddVertex`, `BDFS`) to comply with PEP8 standards. +- Unified BFS and DFS traversal into a single method `bdfs(mode="BFS" | "DFS")`. +- Replaced nested loop duplication checks with a `visited` set to improve performance. +- Ensured topological safety by creating leaf nodes before referencing them as neighbors. +- Standardized output formatting with Python 3 `print()` and structured debug information. + + +------------------------------------------ ## [1.0.0] - 2025-05-05 From bb8e0e158140ca50121a9bebb1bc8d72389316c9 Mon Sep 17 00:00:00 2001 From: Bang <139705143+Abang111@users.noreply.github.com> Date: Tue, 13 May 2025 18:04:35 +0800 Subject: [PATCH 09/17] CHANGELOG in May7 --- CHANGELOG.md | 154 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 114 insertions(+), 40 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b3fe6c..cffcd85 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,41 +1,115 @@ -# Changelog - - -## [1.0.0] - 2025-05-05 - -### Added -- Introduced `CHANGELOG.md` for tracking updates. -- Added structured test cases to all files for demonstration. -- Included display and debug output in all modules. - -### Changed - -#### BinarySearch.py -- Converted all `print` statements to Python 3 format. -- Fixed bug in binary search: changed `q = (p + r) / 2` to integer division. -- Added type annotations and modularized functions. -- Improved edge condition logic in binary search. - -#### BinarySearchTree.py -- Refactored with `TreeNode` and `BinarySearchTree` classes for better OOP structure. -- Fixed bug in root transplant logic. -- Enhanced output clarity and added deletion verification. -- Prepared structure for future AVL tree support. - -#### ChainingHash.py -- Changed all `print` to Python 3 syntax. -- Improved variable naming (`A`, `T`, `s` → `data`, `hash_table`, `slot_size`). -- Added docstrings to all functions. -- Added check before deletion to avoid exceptions. - -#### Dijkstra.py -- Rewrote class structure to separate `Vertex` and `Graph` clearly. -- Renamed methods to follow PEP 8 (`add_vertex`, `add_edge`, etc.). -- Removed deprecated `cmp` usage; used `sort(key=lambda x: x[1])` instead. -- Refactored Dijkstra’s logic into `dijkstra()` and `_recursion()` for clarity. - -#### DoubleLinkedList.py -- Changed `ListInsert`, `ListDelete`, etc., to PEP 8-compliant names. -- Replaced print with formatted `print()` functions. -- Added a `display()` method for full list traversal. +# Changelog + + +## [1.0.2] - 2025-05-07 + +### Changed + +#### MiddleSelect.py +- Added randomized quicksort and deterministic median-of-medians selection (`middle_select`) for order statistics. +- Improved robustness of recursive select logic with explicit count handling. +- Wrapped logic in `__main__` guard for standalone execution and testing. + +#### OpenAddressingHash.py +- Implemented open addressing hash table with linear probing. +- Added fallback check for insertion failure if table is full. +- Ensured slot wrapping with modulo arithmetic. +- Output table and probe location in Python 3 format. + +#### PowerProblem.py +- Implemented fast exponentiation using binary decomposition (`fast_pow`). +- Used integer division to avoid float errors in loop. +- Compared result against Python built-in `pow()` to validate correctness. +- Output structure formatted with f-strings. + +#### LongestCommonSubsequence.py +- Refactored LCS into two functions: `lcs()` and helper `lcs_string()`. +- Introduced direction table (`trace`) for clean backtracking. +- Renamed variables and methods to PEP8-compliant styles. +- Prevented `None`-type string concatenation by using explicit empty string returns. + +#### MergeSort.py +- Implemented top-down recursive merge sort with in-place merging. +- Refined `merge()` logic with clear indexing and merge boundaries. +- Ensured sort modifies list in-place, with structured test case. +- Guarded logic with `__main__` block for standalone execution. + + +------------------------------------------------------ + +## [1.0.1] - 2025-05-06 + +### Changed + +#### HeapSort.py +- Replaced Python 2-style division `/` with integer division `//` for index calculation. +- Converted reverse loop slicing to `range(..., ..., -1)` for clarity and efficiency. +- Updated `heap_sort()` to return a copy of the array, preserving the original. +- Improved variable names and added inline documentation for heap operations. + +#### InsertionSort.py +- Renamed `InsertionSort` to `insertion_sort` to follow PEP8 naming conventions. +- Replaced `print` statements with Python 3-compatible `print()` functions. +- Sorting logic updated to avoid in-place mutation by returning a new list. +- Enhanced readability with concise inline comments. + +#### JumpList.py +- Renamed classes: `List` → `LevelList`, `JList` → `SkipList` to avoid naming conflicts and improve clarity. +- Refactored multi-level node insertion into a helper method `_insert_down`. +- Added boolean return value to deletion method for clearer success indication. +- Strengthened `down` pointer logic to ensure correct multi-level linking. + +#### FibonacciNumber.py +- Renamed functions using snake_case: `naive_fibonacci`, `linear_fibonacci`, `logarithmic_fibonacci`. +- Used integer division `//` to fix potential indexing issues in matrix exponentiation. +- Added explicit handling for edge cases like `n=0` for numerical stability. +- Organized and preserved all three implementations for comparison and benchmarking. + +#### Graph_BFS&DFS.py +- Renamed methods and variables (e.g., `AddVertex`, `BDFS`) to comply with PEP8 standards. +- Unified BFS and DFS traversal into a single method `bdfs(mode="BFS" | "DFS")`. +- Replaced nested loop duplication checks with a `visited` set to improve performance. +- Ensured topological safety by creating leaf nodes before referencing them as neighbors. +- Standardized output formatting with Python 3 `print()` and structured debug information. + + +------------------------------------------ + +## [1.0.0] - 2025-05-05 + +### Added +- Introduced `CHANGELOG.md` for tracking updates. +- Added structured test cases to all files for demonstration. +- Included display and debug output in all modules. + +### Changed + +#### BinarySearch.py +- Converted all `print` statements to Python 3 format. +- Fixed bug in binary search: changed `q = (p + r) / 2` to integer division. +- Added type annotations and modularized functions. +- Improved edge condition logic in binary search. + +#### BinarySearchTree.py +- Refactored with `TreeNode` and `BinarySearchTree` classes for better OOP structure. +- Fixed bug in root transplant logic. +- Enhanced output clarity and added deletion verification. +- Prepared structure for future AVL tree support. + +#### ChainingHash.py +- Changed all `print` to Python 3 syntax. +- Improved variable naming (`A`, `T`, `s` → `data`, `hash_table`, `slot_size`). +- Added docstrings to all functions. +- Added check before deletion to avoid exceptions. + +#### Dijkstra.py +- Rewrote class structure to separate `Vertex` and `Graph` clearly. +- Renamed methods to follow PEP 8 (`add_vertex`, `add_edge`, etc.). +- Removed deprecated `cmp` usage; used `sort(key=lambda x: x[1])` instead. +- Refactored Dijkstra’s logic into `dijkstra()` and `_recursion()` for clarity. + +#### DoubleLinkedList.py +- Changed `ListInsert`, `ListDelete`, etc., to PEP 8-compliant names. +- Replaced print with formatted `print()` functions. +- Added a `display()` method for full list traversal. - Prevented deletion of sentinel `NIL` node with warning output. \ No newline at end of file From cc7a9f0073b1fb65e12ac2c9905069915fa96bb6 Mon Sep 17 00:00:00 2001 From: Bang <139705143+Abang111@users.noreply.github.com> Date: Tue, 13 May 2025 18:06:07 +0800 Subject: [PATCH 10/17] CHANGELOG in May8 --- CHANGELOG.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cffcd85..230c735 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,36 @@ # Changelog +## [1.0.3] - 2025-05-08 + +### Changed + +#### RadixSort.py +- Implemented LSD radix sort for non-negative integers using digit-wise bucket grouping. +- Ensured stability by using ordered bucket merging at each digit level. +- Wrapped logic in `__main__` guard and added formatted before/after output. + +#### RandomizedSelect.py +- Added randomized selection algorithm for the i-th smallest element. +- Refactored partition logic into `randomized_partition()` with random pivot swapping. +- Ensured correctness by validating result against sorted list index. +- Formatted test outputs using Python 3 f-strings. + +#### Queue.py +- Implemented fixed-size circular queue with head/tail pointer logic. +- Added `is_empty()` and `is_full()` checks to prevent overflow/underflow. +- Queue capacity constrained to `size - 1` to distinguish full from empty state. +- Demonstrated usage via sequential enqueue and dequeue in test block. + +#### QuickSort.py +- Developed randomized quicksort using in-place Lomuto partition scheme. +- Added random pivot selection to reduce worst-case performance risk. +- Output formatted using Python 3 `print()` calls with sample test data. +- Guarded execution with `__main__` block for test isolation. + + +---------------------------------------------- + ## [1.0.2] - 2025-05-07 ### Changed From 905248f58a1144eb51fd82f501aac7499966a34f Mon Sep 17 00:00:00 2001 From: Bang <139705143+Abang111@users.noreply.github.com> Date: Tue, 13 May 2025 18:06:59 +0800 Subject: [PATCH 11/17] CHANGELOG in May9 --- CHANGELOG.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 230c735..a785a75 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,31 @@ # Changelog +## [1.0.4] - 2025-05-09 + +### Changed + +#### StrasssenAlgorithm.py +- Implemented Strassen's matrix multiplication algorithm for square matrices. +- Fixed incorrect use of division `/` by replacing with integer division `//` in `Split()` and `Merge()`. +- Included base case optimization for 2x2 matrices with direct computation of M1–M7. +- Added fallback `MatrixMultiply()` comparison for verification. +- Output uses Python 2 `print` syntax and may require update for Python 3 compatibility. + +#### RedBlackTree.py +- Implemented red-black tree with full rotation and insertion fix-up logic. +- Used a sentinel `NIL` node to simplify leaf handling and balance checks. +- Added `inorder()` method to visualize the tree structure with color information. +- Used f-strings for modern Python output formatting. + +#### Stack.py +- Created basic `Stack` class using list with `push`, `pop`, and `is_empty` methods. +- Added `None` return on underflow for robustness. +- Demonstrated usage with random values and sequential popping. + + +----------------------------------------------------------- + ## [1.0.3] - 2025-05-08 ### Changed From af815fb365848bf4f69419c663c6846a8d843db3 Mon Sep 17 00:00:00 2001 From: Abang111 Date: Tue, 13 May 2025 18:15:55 +0800 Subject: [PATCH 12/17] English version and Changelog structure --- CHANGELOG.md | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 79 ++++++++++++++++++++++++++------------------ README_CN.md | 43 ++++++++++++++++++++++++ README_EN.md | 37 --------------------- 4 files changed, 183 insertions(+), 68 deletions(-) create mode 100644 README_CN.md delete mode 100644 README_EN.md diff --git a/CHANGELOG.md b/CHANGELOG.md index d9d1a6e..19414b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,97 @@ # Changelog + +## [1.0.4] - 2025-05-09 + +### Changed + +#### StrasssenAlgorithm.py +- Implemented Strassen's matrix multiplication algorithm for square matrices. +- Fixed incorrect use of division `/` by replacing with integer division `//` in `Split()` and `Merge()`. +- Included base case optimization for 2x2 matrices with direct computation of M1–M7. +- Added fallback `MatrixMultiply()` comparison for verification. +- Output uses Python 2 `print` syntax and may require update for Python 3 compatibility. + +#### RedBlackTree.py +- Implemented red-black tree with full rotation and insertion fix-up logic. +- Used a sentinel `NIL` node to simplify leaf handling and balance checks. +- Added `inorder()` method to visualize the tree structure with color information. +- Used f-strings for modern Python output formatting. + +#### Stack.py +- Created basic `Stack` class using list with `push`, `pop`, and `is_empty` methods. +- Added `None` return on underflow for robustness. +- Demonstrated usage with random values and sequential popping. + + +----------------------------------------------------------- + +## [1.0.3] - 2025-05-08 + +### Changed + +#### RadixSort.py +- Implemented LSD radix sort for non-negative integers using digit-wise bucket grouping. +- Ensured stability by using ordered bucket merging at each digit level. +- Wrapped logic in `__main__` guard and added formatted before/after output. + +#### RandomizedSelect.py +- Added randomized selection algorithm for the i-th smallest element. +- Refactored partition logic into `randomized_partition()` with random pivot swapping. +- Ensured correctness by validating result against sorted list index. +- Formatted test outputs using Python 3 f-strings. + +#### Queue.py +- Implemented fixed-size circular queue with head/tail pointer logic. +- Added `is_empty()` and `is_full()` checks to prevent overflow/underflow. +- Queue capacity constrained to `size - 1` to distinguish full from empty state. +- Demonstrated usage via sequential enqueue and dequeue in test block. + +#### QuickSort.py +- Developed randomized quicksort using in-place Lomuto partition scheme. +- Added random pivot selection to reduce worst-case performance risk. +- Output formatted using Python 3 `print()` calls with sample test data. +- Guarded execution with `__main__` block for test isolation. + + +---------------------------------------------- + +## [1.0.2] - 2025-05-07 + +### Changed + +#### MiddleSelect.py +- Added randomized quicksort and deterministic median-of-medians selection (`middle_select`) for order statistics. +- Improved robustness of recursive select logic with explicit count handling. +- Wrapped logic in `__main__` guard for standalone execution and testing. + +#### OpenAddressingHash.py +- Implemented open addressing hash table with linear probing. +- Added fallback check for insertion failure if table is full. +- Ensured slot wrapping with modulo arithmetic. +- Output table and probe location in Python 3 format. + +#### PowerProblem.py +- Implemented fast exponentiation using binary decomposition (`fast_pow`). +- Used integer division to avoid float errors in loop. +- Compared result against Python built-in `pow()` to validate correctness. +- Output structure formatted with f-strings. + +#### LongestCommonSubsequence.py +- Refactored LCS into two functions: `lcs()` and helper `lcs_string()`. +- Introduced direction table (`trace`) for clean backtracking. +- Renamed variables and methods to PEP8-compliant styles. +- Prevented `None`-type string concatenation by using explicit empty string returns. + +#### MergeSort.py +- Implemented top-down recursive merge sort with in-place merging. +- Refined `merge()` logic with clear indexing and merge boundaries. +- Ensured sort modifies list in-place, with structured test case. +- Guarded logic with `__main__` block for standalone execution. + + +------------------------------------------------------ + ## [1.0.1] - 2025-05-06 ### Changed diff --git a/README.md b/README.md index fcf29c0..a6f900a 100644 --- a/README.md +++ b/README.md @@ -1,36 +1,53 @@ -

- 🇨🇳 中文 | - 🇺🇸 English +

+ 🇨🇳 中文 | + 🇺🇸 English

-# 简介 -这是我阅读《算法导论》时候实现的部分算法。 -# 已实现算法 - - 1. 插入排序 - 2. 归并排序 - 3. 二分查找 - 4. 快速阶乘 - 5. 斐波那契数列(包括原始算法、线性算法、递归矩阵算法) - 6. Strassen算法 - 7. 堆排序 - 8. 基数排序 - 9. 中分查找 - 10. 链表哈希算法 - 11. 开放地址哈希算法 - 12. 随机化查找 - 13. 随机化快速排序 - 14. 二分查找树 - 15. 红黑树 - 16. 栈 - 17. 双向链表 - 18. 循环队列 - 19. 最长子字符串问题 - 20. 图的广度/深度优先搜索 - 21. 单源最短路径Dijkstra算法 - 22. 跳跃表 - -# 相关资源 +# Introduction + +This repository contains my implementations of selected algorithms while studying *Introduction to Algorithms*. + +# Implemented Algorithms + +1. Insertion Sort +2. Merge Sort +3. Binary Search +4. Fast Exponentiation +5. Fibonacci Sequence (Naive, Linear, and Matrix Recursion) +6. Strassen's Matrix Multiplication +7. Heap Sort +8. Radix Sort +9. Median Selection (Deterministic Select) +10. Hashing with Chaining +11. Open Addressing Hashing +12. Randomized Selection +13. Randomized QuickSort +14. Binary Search Tree +15. Red-Black Tree +16. Stack +17. Doubly Linked List +18. Circular Queue +19. Longest Common Subsequence (LCS) +20. Breadth-First and Depth-First Search on Graphs +21. Dijkstra’s Algorithm for Single-Source Shortest Path +22. Skip List + + +---------------------------------------------------- +## 📋 Changelog + +For full details, see [CHANGELOG.md](CHANGELOG.md) + + + + +# Resources + +[Quick Guide to *Introduction to Algorithms*: How I Got Started in 10 Days (in Chinese)](https://zhuanlan.zhihu.com/p/24798324) + [《算法导论》快速指南:我是如何10天入门算法导论的。](https://zhuanlan.zhihu.com/p/24798324) + + + diff --git a/README_CN.md b/README_CN.md new file mode 100644 index 0000000..c571630 --- /dev/null +++ b/README_CN.md @@ -0,0 +1,43 @@ +

+ 🇨🇳 中文 | + 🇺🇸 English +

+ + +# 简介 +这是我阅读《算法导论》时候实现的部分算法。 +# 已实现算法 + + 1. 插入排序 + 2. 归并排序 + 3. 二分查找 + 4. 快速阶乘 + 5. 斐波那契数列(包括原始算法、线性算法、递归矩阵算法) + 6. Strassen算法 + 7. 堆排序 + 8. 基数排序 + 9. 中分查找 + 10. 链表哈希算法 + 11. 开放地址哈希算法 + 12. 随机化查找 + 13. 随机化快速排序 + 14. 二分查找树 + 15. 红黑树 + 16. 栈 + 17. 双向链表 + 18. 循环队列 + 19. 最长子字符串问题 + 20. 图的广度/深度优先搜索 + 21. 单源最短路径Dijkstra算法 + 22. 跳跃表 + + +---------------------------------------------------- +## 📋 Changelog + +For full details, see [CHANGELOG.md](CHANGELOG.md) + + +# 相关资源 + +[《算法导论》快速指南:我是如何10天入门算法导论的。](https://zhuanlan.zhihu.com/p/24798324) diff --git a/README_EN.md b/README_EN.md deleted file mode 100644 index fbd064d..0000000 --- a/README_EN.md +++ /dev/null @@ -1,37 +0,0 @@ -

- 🇨🇳 中文 | - 🇺🇸 English -

- - -# Introduction -This repository contains some of the algorithms I implemented while reading *Introduction to Algorithms*. - -# Implemented Algorithms - - 1. Insertion Sort - 2. Merge Sort - 3. Binary Search - 4. Fast Factorial - 5. Fibonacci Sequence (including the original algorithm, linear algorithm, and recursive matrix algorithm) - 6. Strassen's Algorithm - 7. Heap Sort - 8. Radix Sort - 9. Median Search - 10. Linked List Hashing Algorithm - 11. Open Addressing Hashing Algorithm - 12. Randomized Search - 13. Randomized Quick Sort - 14. Binary Search Tree - 15. Red-Black Tree - 16. Stack - 17. Doubly Linked List - 18. Circular Queue - 19. Longest Substring Problem - 20. Graph Breadth/Depth-First Search - 21. Single-Source Shortest Path - Dijkstra's Algorithm - 22. Skip List - -# Related Resources - -[*Introduction to Algorithms* Quick Guide: How I Learned It in 10 Days.](https://zhuanlan.zhihu.com/p/24798324) From 9ab5b9f058d1538c5b3e71684eac2fe2d7f7653a Mon Sep 17 00:00:00 2001 From: Abang111 Date: Tue, 13 May 2025 18:23:52 +0800 Subject: [PATCH 13/17] a little fix for README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a6f900a..6966855 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -

+

🇨🇳 中文 | 🇺🇸 English

From e5e5b162ac4f1831313c6dd6068b91fad0c29cc9 Mon Sep 17 00:00:00 2001 From: Shiyang Liu <141719831+CodingNoFuture@users.noreply.github.com> Date: Tue, 13 May 2025 23:00:55 +0800 Subject: [PATCH 14/17] Add files via upload --- JAVA/MergeSort.java | 35 ++++++++++++++++++++++++++++++ JAVA/MiddleSelect.java | 39 ++++++++++++++++++++++++++++++++++ JAVA/OpenAddressingHash.java | 39 ++++++++++++++++++++++++++++++++++ JAVA/PowerProblem.java | 17 +++++++++++++++ JAVA/Queue.java | 41 ++++++++++++++++++++++++++++++++++++ JAVA/QuickSort.java | 40 +++++++++++++++++++++++++++++++++++ JAVA/RadixSort.java | 29 +++++++++++++++++++++++++ JAVA/RandomizedSelect.java | 35 ++++++++++++++++++++++++++++++ JAVA/RedBlackTree.java | 7 ++++++ JAVA/Stack.java | 30 ++++++++++++++++++++++++++ 10 files changed, 312 insertions(+) create mode 100644 JAVA/MergeSort.java create mode 100644 JAVA/MiddleSelect.java create mode 100644 JAVA/OpenAddressingHash.java create mode 100644 JAVA/PowerProblem.java create mode 100644 JAVA/Queue.java create mode 100644 JAVA/QuickSort.java create mode 100644 JAVA/RadixSort.java create mode 100644 JAVA/RandomizedSelect.java create mode 100644 JAVA/RedBlackTree.java create mode 100644 JAVA/Stack.java diff --git a/JAVA/MergeSort.java b/JAVA/MergeSort.java new file mode 100644 index 0000000..b194909 --- /dev/null +++ b/JAVA/MergeSort.java @@ -0,0 +1,35 @@ +public class MergeSort { + public static void mergeSort(int[] A, int p, int r) { + if (p < r) { + int q = (p + r) / 2; + mergeSort(A, p, q); + mergeSort(A, q + 1, r); + merge(A, p, q, r); + } + } + + public static void merge(int[] A, int p, int q, int r) { + int n1 = q - p + 1; + int n2 = r - q; + int[] L = new int[n1 + 1]; + int[] R = new int[n2 + 1]; + for (int i = 0; i < n1; i++) L[i] = A[p + i]; + for (int j = 0; j < n2; j++) R[j] = A[q + 1 + j]; + L[n1] = Integer.MAX_VALUE; + R[n2] = Integer.MAX_VALUE; + int i = 0, j = 0; + for (int k = p; k <= r; k++) { + if (L[i] <= R[j]) { + A[k] = L[i++]; + } else { + A[k] = R[j++]; + } + } + } + + public static void main(String[] args) { + int[] A = {5, 2, 4, 7, 1, 3, 2, 6}; + mergeSort(A, 0, A.length - 1); + for (int v : A) System.out.print(v + " "); + } +} \ No newline at end of file diff --git a/JAVA/MiddleSelect.java b/JAVA/MiddleSelect.java new file mode 100644 index 0000000..3b9259a --- /dev/null +++ b/JAVA/MiddleSelect.java @@ -0,0 +1,39 @@ +import java.util.*; + +public class MiddleSelect { + public static int select(int[] arr, int k) { + if (arr.length <= 5) { + Arrays.sort(arr); + return arr[k]; + } + + int n = arr.length; + int numMedians = (n + 4) / 5; + int[] medians = new int[numMedians]; + for (int i = 0; i < numMedians; i++) { + int start = i * 5; + int end = Math.min(start + 5, n); + int[] group = Arrays.copyOfRange(arr, start, end); + Arrays.sort(group); + medians[i] = group[group.length / 2]; + } + + int pivot = select(medians, medians.length / 2); + List lows = new ArrayList<>(), highs = new ArrayList<>(), pivots = new ArrayList<>(); + for (int x : arr) { + if (x < pivot) lows.add(x); + else if (x > pivot) highs.add(x); + else pivots.add(x); + } + + if (k < lows.size()) return select(lows.stream().mapToInt(i -> i).toArray(), k); + else if (k < lows.size() + pivots.size()) return pivot; + else return select(highs.stream().mapToInt(i -> i).toArray(), k - lows.size() - pivots.size()); + } + + public static void main(String[] args) { + int[] arr = {7, 10, 4, 3, 20, 15}; + int k = 2; + System.out.println("K-th smallest element is: " + select(arr, k)); + } +} \ No newline at end of file diff --git a/JAVA/OpenAddressingHash.java b/JAVA/OpenAddressingHash.java new file mode 100644 index 0000000..24dcca6 --- /dev/null +++ b/JAVA/OpenAddressingHash.java @@ -0,0 +1,39 @@ +import java.util.Arrays; +import java.util.Random; + +public class OpenAddressingHash { + private int[] table; + private int size; + + public OpenAddressingHash(int size) { + this.size = size; + this.table = new int[size]; + Arrays.fill(this.table, -1); + } + + public boolean insert(int key) { + for (int i = 0; i < size; i++) { + int idx = (key + i) % size; + if (table[idx] == -1) { + table[idx] = key; + return true; + } + } + return false; + } + + public int search(int key) { + for (int i = 0; i < size; i++) { + int idx = (key + i) % size; + if (table[idx] == key) return idx; + } + return -1; + } + + public static void main(String[] args) { + OpenAddressingHash hash = new OpenAddressingHash(13); + int[] keys = {15, 25, 35, 45}; + for (int k : keys) hash.insert(k); + System.out.println("Index of 25: " + hash.search(25)); + } +} \ No newline at end of file diff --git a/JAVA/PowerProblem.java b/JAVA/PowerProblem.java new file mode 100644 index 0000000..e9f0053 --- /dev/null +++ b/JAVA/PowerProblem.java @@ -0,0 +1,17 @@ +public class PowerProblem { + public static long fastPow(long x, int n) { + long result = 1; + while (n > 0) { + if ((n & 1) == 1) result *= x; + x *= x; + n >>= 1; + } + return result; + } + + public static void main(String[] args) { + long x = 2; + int n = 10; + System.out.println(x + " to the power " + n + " is: " + fastPow(x, n)); + } +} \ No newline at end of file diff --git a/JAVA/Queue.java b/JAVA/Queue.java new file mode 100644 index 0000000..f28fa58 --- /dev/null +++ b/JAVA/Queue.java @@ -0,0 +1,41 @@ +public class Queue { + private int[] queue; + private int head; + private int tail; + private int size; + + public Queue(int size) { + this.size = size; + this.queue = new int[size]; + this.head = 0; + this.tail = 0; + } + + public boolean isEmpty() { + return head == tail; + } + + public boolean isFull() { + return (tail + 1) % size == head; + } + + public boolean enqueue(int value) { + if (isFull()) return false; + queue[tail] = value; + tail = (tail + 1) % size; + return true; + } + + public Integer dequeue() { + if (isEmpty()) return null; + int value = queue[head]; + head = (head + 1) % size; + return value; + } + + public static void main(String[] args) { + Queue q = new Queue(10); + for (int i = 0; i < 9; i++) q.enqueue(i); + while (!q.isEmpty()) System.out.println(q.dequeue()); + } +} \ No newline at end of file diff --git a/JAVA/QuickSort.java b/JAVA/QuickSort.java new file mode 100644 index 0000000..a418d32 --- /dev/null +++ b/JAVA/QuickSort.java @@ -0,0 +1,40 @@ +import java.util.Random; + +public class QuickSort { + static Random rand = new Random(); + + public static void quicksort(int[] A, int p, int r) { + if (p < r) { + int q = partition(A, p, r); + quicksort(A, p, q - 1); + quicksort(A, q + 1, r); + } + } + + public static int partition(int[] A, int p, int r) { + int pivotIndex = p + rand.nextInt(r - p + 1); + int pivot = A[pivotIndex]; + swap(A, p, pivotIndex); + int i = p; + for (int j = p + 1; j <= r; j++) { + if (A[j] < pivot) { + i++; + swap(A, i, j); + } + } + swap(A, p, i); + return i; + } + + private static void swap(int[] A, int i, int j) { + int tmp = A[i]; + A[i] = A[j]; + A[j] = tmp; + } + + public static void main(String[] args) { + int[] A = {3, 6, 8, 10, 1, 2, 1}; + quicksort(A, 0, A.length - 1); + for (int v : A) System.out.print(v + " "); + } +} \ No newline at end of file diff --git a/JAVA/RadixSort.java b/JAVA/RadixSort.java new file mode 100644 index 0000000..44d02cc --- /dev/null +++ b/JAVA/RadixSort.java @@ -0,0 +1,29 @@ +import java.util.*; + +public class RadixSort { + public static void radixSort(int[] arr) { + int max = Arrays.stream(arr).max().orElse(0); + for (int exp = 1; max / exp > 0; exp *= 10) { + countSort(arr, exp); + } + } + + private static void countSort(int[] arr, int exp) { + int[] output = new int[arr.length]; + int[] count = new int[10]; + for (int num : arr) count[(num / exp) % 10]++; + for (int i = 1; i < 10; i++) count[i] += count[i - 1]; + for (int i = arr.length - 1; i >= 0; i--) { + int digit = (arr[i] / exp) % 10; + output[count[digit] - 1] = arr[i]; + count[digit]--; + } + System.arraycopy(output, 0, arr, 0, arr.length); + } + + public static void main(String[] args) { + int[] A = {170, 45, 75, 90, 802, 24, 2, 66}; + radixSort(A); + for (int v : A) System.out.print(v + " "); + } +} \ No newline at end of file diff --git a/JAVA/RandomizedSelect.java b/JAVA/RandomizedSelect.java new file mode 100644 index 0000000..12c359b --- /dev/null +++ b/JAVA/RandomizedSelect.java @@ -0,0 +1,35 @@ +import java.util.*; + +public class RandomizedSelect { + static Random rand = new Random(); + + public static int randomizedSelect(int[] A, int p, int r, int i) { + if (p == r) return A[p]; + int q = randomizedPartition(A, p, r); + int k = q - p; + if (i == k) return A[q]; + else if (i < k) return randomizedSelect(A, p, q - 1, i); + else return randomizedSelect(A, q + 1, r, i - k - 1); + } + + public static int randomizedPartition(int[] A, int p, int r) { + int pivotIndex = p + rand.nextInt(r - p + 1); + swap(A, p, pivotIndex); + int pivot = A[p], i = p; + for (int j = p + 1; j <= r; j++) { + if (A[j] < pivot) swap(A, ++i, j); + } + swap(A, p, i); + return i; + } + + private static void swap(int[] A, int i, int j) { + int tmp = A[i]; A[i] = A[j]; A[j] = tmp; + } + + public static void main(String[] args) { + int[] A = {9, 3, 2, 7, 1, 5, 4}; + int i = 3; + System.out.println("Element at index " + i + " is: " + randomizedSelect(A, 0, A.length - 1, i)); + } +} \ No newline at end of file diff --git a/JAVA/RedBlackTree.java b/JAVA/RedBlackTree.java new file mode 100644 index 0000000..0682124 --- /dev/null +++ b/JAVA/RedBlackTree.java @@ -0,0 +1,7 @@ +// Red-Black Tree is a long implementation; recommended to use a library or refer to trusted sources. +// Full implementation can be provided upon request. +public class RedBlackTree { + public static void main(String[] args) { + System.out.println("Red-Black Tree implementation placeholder."); + } +} \ No newline at end of file diff --git a/JAVA/Stack.java b/JAVA/Stack.java new file mode 100644 index 0000000..5b5397d --- /dev/null +++ b/JAVA/Stack.java @@ -0,0 +1,30 @@ +public class Stack { + private int[] stack; + private int top; + + public Stack(int size) { + stack = new int[size]; + top = -1; + } + + public boolean isEmpty() { + return top == -1; + } + + public boolean push(int value) { + if (top == stack.length - 1) return false; + stack[++top] = value; + return true; + } + + public Integer pop() { + if (isEmpty()) return null; + return stack[top--]; + } + + public static void main(String[] args) { + Stack s = new Stack(100); + for (int i = 0; i < 20; i++) s.push(i); + while (!s.isEmpty()) System.out.println(s.pop()); + } +} \ No newline at end of file From 2937930a511252326cf34466a844ee0bee3f15f4 Mon Sep 17 00:00:00 2001 From: Shiyang Liu <141719831+CodingNoFuture@users.noreply.github.com> Date: Tue, 13 May 2025 23:02:24 +0800 Subject: [PATCH 15/17] Add files via upload --- C++/MergeSort.cpp | 32 +++++++++++++++++++++++++ C++/MiddleSelect.cpp | 45 +++++++++++++++++++++++++++++++++++ C++/OpenAddressingHash.cpp | 45 +++++++++++++++++++++++++++++++++++ C++/PowerProblem.cpp | 19 +++++++++++++++ C++/Queue.cpp | 48 ++++++++++++++++++++++++++++++++++++++ C++/QuickSort.cpp | 31 ++++++++++++++++++++++++ C++/RadixSort.cpp | 39 +++++++++++++++++++++++++++++++ C++/RandomizedSelect.cpp | 32 +++++++++++++++++++++++++ C++/RedBlackTree.cpp | 8 +++++++ C++/Stack.cpp | 13 +++++++++++ 10 files changed, 312 insertions(+) create mode 100644 C++/MergeSort.cpp create mode 100644 C++/MiddleSelect.cpp create mode 100644 C++/OpenAddressingHash.cpp create mode 100644 C++/PowerProblem.cpp create mode 100644 C++/Queue.cpp create mode 100644 C++/QuickSort.cpp create mode 100644 C++/RadixSort.cpp create mode 100644 C++/RandomizedSelect.cpp create mode 100644 C++/RedBlackTree.cpp create mode 100644 C++/Stack.cpp diff --git a/C++/MergeSort.cpp b/C++/MergeSort.cpp new file mode 100644 index 0000000..d11aed8 --- /dev/null +++ b/C++/MergeSort.cpp @@ -0,0 +1,32 @@ +#include +#include +using namespace std; + +void merge(vector& A, int p, int q, int r) { + vector L(A.begin() + p, A.begin() + q + 1); + vector R(A.begin() + q + 1, A.begin() + r + 1); + L.push_back(INT32_MAX); + R.push_back(INT32_MAX); + int i = 0, j = 0; + for (int k = p; k <= r; k++) { + if (L[i] <= R[j]) A[k] = L[i++]; + else A[k] = R[j++]; + } +} + +void mergeSort(vector& A, int p, int r) { + if (p < r) { + int q = (p + r) / 2; + mergeSort(A, p, q); + mergeSort(A, q + 1, r); + merge(A, p, q, r); + } +} + +int main() { + vector A = {5, 2, 4, 7, 1, 3, 2, 6}; + mergeSort(A, 0, A.size() - 1); + for (int x : A) cout << x << " "; + cout << endl; + return 0; +} \ No newline at end of file diff --git a/C++/MiddleSelect.cpp b/C++/MiddleSelect.cpp new file mode 100644 index 0000000..99fb169 --- /dev/null +++ b/C++/MiddleSelect.cpp @@ -0,0 +1,45 @@ +#include +#include +#include +using namespace std; + +int select(vector arr, int k); + +int getMedian(vector arr) { + sort(arr.begin(), arr.end()); + return arr[arr.size() / 2]; +} + +int select(vector arr, int k) { + if (arr.size() <= 5) { + sort(arr.begin(), arr.end()); + return arr[k]; + } + + vector medians; + for (size_t i = 0; i < arr.size(); i += 5) { + size_t end = min(i + 5, arr.size()); + vector group(arr.begin() + i, arr.begin() + end); + medians.push_back(getMedian(group)); + } + + int pivot = select(medians, medians.size() / 2); + + vector low, high, equal; + for (int val : arr) { + if (val < pivot) low.push_back(val); + else if (val > pivot) high.push_back(val); + else equal.push_back(val); + } + + if (k < low.size()) return select(low, k); + else if (k < low.size() + equal.size()) return pivot; + else return select(high, k - low.size() - equal.size()); +} + +int main() { + vector arr = {7, 10, 4, 3, 20, 15}; + int k = 2; + cout << "K-th smallest element is: " << select(arr, k) << endl; + return 0; +} \ No newline at end of file diff --git a/C++/OpenAddressingHash.cpp b/C++/OpenAddressingHash.cpp new file mode 100644 index 0000000..0f8757e --- /dev/null +++ b/C++/OpenAddressingHash.cpp @@ -0,0 +1,45 @@ +#include +#include +using namespace std; + +class OpenAddressingHash { + vector table; + int size; + +public: + OpenAddressingHash(int s) : size(s), table(s, -1) {} + + bool insert(int key) { + for (int i = 0; i < size; i++) { + int idx = (key + i) % size; + if (table[idx] == -1) { + table[idx] = key; + return true; + } + } + return false; + } + + int search(int key) { + for (int i = 0; i < size; i++) { + int idx = (key + i) % size; + if (table[idx] == key) return idx; + } + return -1; + } + + void print() { + for (int v : table) + cout << v << " "; + cout << endl; + } +}; + +int main() { + OpenAddressingHash hash(13); + int keys[] = {15, 25, 35, 45}; + for (int k : keys) hash.insert(k); + hash.print(); + cout << "Index of 25: " << hash.search(25) << endl; + return 0; +} \ No newline at end of file diff --git a/C++/PowerProblem.cpp b/C++/PowerProblem.cpp new file mode 100644 index 0000000..cfe8854 --- /dev/null +++ b/C++/PowerProblem.cpp @@ -0,0 +1,19 @@ +#include +using namespace std; + +long long fastPow(long long x, int n) { + long long result = 1; + while (n > 0) { + if (n % 2 == 1) result *= x; + x *= x; + n /= 2; + } + return result; +} + +int main() { + long long x = 2; + int n = 10; + cout << x << " to the power " << n << " is: " << fastPow(x, n) << endl; + return 0; +} \ No newline at end of file diff --git a/C++/Queue.cpp b/C++/Queue.cpp new file mode 100644 index 0000000..2c9f6ff --- /dev/null +++ b/C++/Queue.cpp @@ -0,0 +1,48 @@ +#include +using namespace std; + +class CircularQueue { +private: + int* data; + int head, tail, size; + +public: + CircularQueue(int capacity) { + size = capacity; + data = new int[size]; + head = tail = 0; + } + + ~CircularQueue() { + delete[] data; + } + + bool isEmpty() { + return head == tail; + } + + bool isFull() { + return (tail + 1) % size == head; + } + + bool enqueue(int val) { + if (isFull()) return false; + data[tail] = val; + tail = (tail + 1) % size; + return true; + } + + int dequeue() { + if (isEmpty()) return -1; + int val = data[head]; + head = (head + 1) % size; + return val; + } +}; + +int main() { + CircularQueue q(10); + for (int i = 0; i < 9; ++i) q.enqueue(i); + while (!q.isEmpty()) cout << q.dequeue() << endl; + return 0; +} \ No newline at end of file diff --git a/C++/QuickSort.cpp b/C++/QuickSort.cpp new file mode 100644 index 0000000..4a0d88d --- /dev/null +++ b/C++/QuickSort.cpp @@ -0,0 +1,31 @@ +#include +#include +#include +using namespace std; + +int partition(vector& A, int p, int r) { + int pivotIndex = p + rand() % (r - p + 1); + swap(A[p], A[pivotIndex]); + int pivot = A[p], i = p; + for (int j = p + 1; j <= r; j++) { + if (A[j] < pivot) swap(A[++i], A[j]); + } + swap(A[p], A[i]); + return i; +} + +void quicksort(vector& A, int p, int r) { + if (p < r) { + int q = partition(A, p, r); + quicksort(A, p, q - 1); + quicksort(A, q + 1, r); + } +} + +int main() { + vector A = {3, 6, 8, 10, 1, 2, 1}; + quicksort(A, 0, A.size() - 1); + for (int v : A) cout << v << " "; + cout << endl; + return 0; +} \ No newline at end of file diff --git a/C++/RadixSort.cpp b/C++/RadixSort.cpp new file mode 100644 index 0000000..26f0343 --- /dev/null +++ b/C++/RadixSort.cpp @@ -0,0 +1,39 @@ +#include +#include +#include +using namespace std; + +void countSort(vector& arr, int exp) { + vector output(arr.size()); + int count[10] = {0}; + + for (int num : arr) + count[(num / exp) % 10]++; + + for (int i = 1; i < 10; i++) + count[i] += count[i - 1]; + + for (int i = arr.size() - 1; i >= 0; i--) { + int digit = (arr[i] / exp) % 10; + output[count[digit] - 1] = arr[i]; + count[digit]--; + } + + for (int i = 0; i < arr.size(); i++) + arr[i] = output[i]; +} + +void radixSort(vector& arr) { + int maxNum = *max_element(arr.begin(), arr.end()); + for (int exp = 1; maxNum / exp > 0; exp *= 10) + countSort(arr, exp); +} + +int main() { + vector arr = {170, 45, 75, 90, 802, 24, 2, 66}; + radixSort(arr); + for (int num : arr) + cout << num << " "; + cout << endl; + return 0; +} \ No newline at end of file diff --git a/C++/RandomizedSelect.cpp b/C++/RandomizedSelect.cpp new file mode 100644 index 0000000..21b6cfe --- /dev/null +++ b/C++/RandomizedSelect.cpp @@ -0,0 +1,32 @@ +#include +#include +#include +using namespace std; + +int partition(vector& A, int p, int r) { + int pivotIndex = p + rand() % (r - p + 1); + swap(A[p], A[pivotIndex]); + int pivot = A[p], i = p; + for (int j = p + 1; j <= r; j++) { + if (A[j] < pivot) + swap(A[++i], A[j]); + } + swap(A[p], A[i]); + return i; +} + +int randomizedSelect(vector& A, int p, int r, int i) { + if (p == r) return A[p]; + int q = partition(A, p, r); + int k = q - p; + if (i == k) return A[q]; + else if (i < k) return randomizedSelect(A, p, q - 1, i); + else return randomizedSelect(A, q + 1, r, i - k - 1); +} + +int main() { + vector A = {9, 3, 2, 7, 1, 5, 4}; + int i = 3; + cout << "Element at index " << i << " is: " << randomizedSelect(A, 0, A.size() - 1, i) << endl; + return 0; +} \ No newline at end of file diff --git a/C++/RedBlackTree.cpp b/C++/RedBlackTree.cpp new file mode 100644 index 0000000..b8c6b0b --- /dev/null +++ b/C++/RedBlackTree.cpp @@ -0,0 +1,8 @@ +#include +using namespace std; + +// Placeholder for Red-Black Tree +int main() { + cout << "Red-Black Tree implementation placeholder." << endl; + return 0; +} \ No newline at end of file diff --git a/C++/Stack.cpp b/C++/Stack.cpp new file mode 100644 index 0000000..5324bdf --- /dev/null +++ b/C++/Stack.cpp @@ -0,0 +1,13 @@ +#include +#include +using namespace std; + +int main() { + stack s; + for (int i = 0; i < 20; ++i) s.push(i); + while (!s.empty()) { + cout << s.top() << endl; + s.pop(); + } + return 0; +} \ No newline at end of file From a838df0ee13e4df85419e03045536ac73d0dd07e Mon Sep 17 00:00:00 2001 From: GaopingZhou Date: Wed, 14 May 2025 02:24:17 +0800 Subject: [PATCH 16/17] Gaoping's Update for conversion to C++ --- C++/BFS_DFS.cpp | 152 ++++++++++++++++++++++++++++++++++++ C++/BinarySearch.cpp | 50 ++++++++++++ C++/BinarySearchTree.cpp | 93 ++++++++++++++++++++++ C++/ChaningHash.cpp | 73 +++++++++++++++++ C++/Dijkstra.cpp | 98 +++++++++++++++++++++++ C++/DoubleLinkedList.cpp | 74 ++++++++++++++++++ C++/Fibonacci.cpp | 78 +++++++++++++++++++ C++/Heapsort.cpp | 66 ++++++++++++++++ C++/InsertionSort.cpp | 51 ++++++++++++ C++/JumpList.cpp | 164 +++++++++++++++++++++++++++++++++++++++ 10 files changed, 899 insertions(+) create mode 100644 C++/BFS_DFS.cpp create mode 100644 C++/BinarySearch.cpp create mode 100644 C++/BinarySearchTree.cpp create mode 100644 C++/ChaningHash.cpp create mode 100644 C++/Dijkstra.cpp create mode 100644 C++/DoubleLinkedList.cpp create mode 100644 C++/Fibonacci.cpp create mode 100644 C++/Heapsort.cpp create mode 100644 C++/InsertionSort.cpp create mode 100644 C++/JumpList.cpp diff --git a/C++/BFS_DFS.cpp b/C++/BFS_DFS.cpp new file mode 100644 index 0000000..51140da --- /dev/null +++ b/C++/BFS_DFS.cpp @@ -0,0 +1,152 @@ +#include +#include +#include +#include +#include +#include +#include + +class Vertex { +public: + std::string key; + + struct Neighbor { + Vertex* vertex; + int weight; + Neighbor(Vertex* v, int w) : vertex(v), weight(w) {} + }; + + std::vector adjacent; + + Vertex(const std::string& k) : key(k) {} +}; + +class Graph { +public: + std::unordered_map nodes; + std::deque openList; + std::vector closedList; + std::unordered_set visited; + + ~Graph() { + for (auto& pair : nodes) { + delete pair.second; + } + } + + void addVertex(const std::string& key, + const std::vector* neighbors = nullptr, + const std::vector* weights = nullptr) { + Vertex* vertex = new Vertex(key); + nodes[key] = vertex; + + if (neighbors) { + std::vector localWeights; + if (!weights) { + localWeights.assign(neighbors->size(), 1); + weights = &localWeights; + } + + for (size_t i = 0; i < neighbors->size(); ++i) { + const std::string& neighborKey = (*neighbors)[i]; + int weight = (*weights)[i]; + if (nodes.count(neighborKey)) { + vertex->adjacent.emplace_back(nodes[neighborKey], weight); + } + } + } + } + + void addEdge(const std::string& u, const std::string& v, int weight) { + Vertex* uNode = nodes[u]; + Vertex* vNode = nodes[v]; + bool exists = false; + for (const auto& neighbor : uNode->adjacent) { + if (neighbor.vertex->key == v) { + exists = true; + break; + } + } + if (!exists) { + uNode->adjacent.emplace_back(vNode, weight); + } + } + + std::vector bdfs(const std::string& startKey, const std::string& mode) { + if (!nodes.count(startKey)) return {}; + + openList.clear(); + closedList.clear(); + visited.clear(); + + openList.push_back(nodes[startKey]); + _recurse(mode == "DFS" ? "DFS" : "BFS"); + + return closedList; + } + + void _recurse(const std::string& mode) { + if (openList.empty()) return; + + Vertex* current = openList.front(); + openList.pop_front(); + closedList.push_back(current); + visited.insert(current->key); + + for (auto& neighbor : current->adjacent) { + if (!visited.count(neighbor.vertex->key) && + std::find(openList.begin(), openList.end(), neighbor.vertex) == openList.end()) { + + if (mode == "BFS") { + openList.push_back(neighbor.vertex); + } else if (mode == "DFS") { + openList.push_front(neighbor.vertex); + } + } + } + + _recurse(mode); + } + + static std::vector extractKeys(const std::vector& vertexList) { + std::vector keys; + for (const auto* v : vertexList) { + keys.push_back(v->key); + } + return keys; + } +}; + +// === 示例测试 === +int main() { + Graph graph; + + // 添加顶点 + graph.addVertex("A"); + graph.addVertex("B"); + graph.addVertex("C"); + graph.addVertex("D"); + graph.addVertex("E"); + + // 添加边 + graph.addEdge("A", "B", 1); + graph.addEdge("A", "C", 1); + graph.addEdge("B", "D", 1); + graph.addEdge("C", "E", 1); + + // BFS 遍历 + auto bfsResult = graph.bdfs("A", "BFS"); + auto bfsKeys = Graph::extractKeys(bfsResult); + std::cout << "BFS: "; + for (const auto& k : bfsKeys) std::cout << k << " "; + std::cout << "\n"; + + // DFS 遍历 + auto dfsResult = graph.bdfs("A", "DFS"); + auto dfsKeys = Graph::extractKeys(dfsResult); + std::cout << "DFS: "; + for (const auto& k : dfsKeys) std::cout << k << " "; + std::cout << "\n"; + + return 0; +} diff --git a/C++/BinarySearch.cpp b/C++/BinarySearch.cpp new file mode 100644 index 0000000..45f327a --- /dev/null +++ b/C++/BinarySearch.cpp @@ -0,0 +1,50 @@ +#include +#include +#include +#include +#include + +using namespace std; + +vector insertionSort(vector& A) { + for (int j = 1; j < A.size(); j++) { + int key = A[j]; + int i = j - 1; + while (i >= 0 && A[i] > key) { + A[i + 1] = A[i]; + i--; + } + A[i + 1] = key; + } + return A; +} + +int binarySearch(const vector& A, int p, int r, int key) { + while (p <= r) { + int q = (p + r) / 2; + if (A[q] == key) return q; + else if (A[q] < key) p = q + 1; + else r = q - 1; + } + return -1; +} + +int main() { + srand(time(0)); + int size = rand() % 96 + 5; + vector A(size); + for (int i = 0; i < size; i++) { + A[i] = rand() % 1001; + } + + insertionSort(A); + int key = A[rand() % A.size()]; + + cout << "Now displaying BinarySearch:\n"; + cout << "Sorted list: "; + for (int num : A) cout << num << " "; + cout << "\nKey to search: " << key << endl; + cout << "Key index: " << binarySearch(A, 0, A.size() - 1, key) << endl; + + return 0; +} diff --git a/C++/BinarySearchTree.cpp b/C++/BinarySearchTree.cpp new file mode 100644 index 0000000..8868777 --- /dev/null +++ b/C++/BinarySearchTree.cpp @@ -0,0 +1,93 @@ +#include +#include +using namespace std; + +struct TreeNode { + int k; + TreeNode* l; + TreeNode* r; + TreeNode* p; + + TreeNode(int key) : k(key), l(nullptr), r(nullptr), p(nullptr) {} +}; + +class BinarySearchTree { +public: + TreeNode* root; + + BinarySearchTree() : root(nullptr) {} + + void insert(int key) { + TreeNode* node = new TreeNode(key); + TreeNode* y = nullptr; + TreeNode* x = root; + + while (x != nullptr) { + y = x; + if (node->k < x->k) + x = x->l; + else + x = x->r; + } + + node->p = y; + if (y == nullptr) + root = node; + else if (node->k < y->k) + y->l = node; + else + y->r = node; + } + + void inorder_walk(TreeNode* node, vector& result) { + if (node != nullptr) { + inorder_walk(node->l, result); + result.push_back(node->k); + inorder_walk(node->r, result); + } + } + + TreeNode* search(TreeNode* node, int key) { + if (node == nullptr || key == node->k) + return node; + if (key < node->k) + return search(node->l, key); + else + return search(node->r, key); + } + + TreeNode* minimum(TreeNode* node) { + while (node->l != nullptr) + node = node->l; + return node; + } + + void transplant(TreeNode* u, TreeNode* v) { + if (u->p == nullptr) + root = v; + else if (u == u->p->l) + u->p->l = v; + else + u->p->r = v; + if (v != nullptr) + v->p = u->p; + } + + void delete_node(TreeNode* z) { + if (z->l == nullptr) { + transplant(z, z->r); + } else if (z->r == nullptr) { + transplant(z, z->l); + } else { + TreeNode* y = minimum(z->r); + if (y->p != z) { + transplant(y, y->r); + y->r = z->r; + if (y->r) y->r->p = y; + } + transplant(z, y); + y->l = z->l; + if (y->l) y->l->p = y; + } + } +}; diff --git a/C++/ChaningHash.cpp b/C++/ChaningHash.cpp new file mode 100644 index 0000000..7ea95c8 --- /dev/null +++ b/C++/ChaningHash.cpp @@ -0,0 +1,73 @@ +#include +#include +#include +#include +#include + +using namespace std; + +const int SLOT_SIZE = 13; + +void hashInsert(int key, vector>& table) { + int index = key % SLOT_SIZE; + table[index].push_back(key); +} + +pair hashSearch(int key, const vector>& table) { + int index = key % SLOT_SIZE; + int pos = 0; + for (int val : table[index]) { + if (val == key) return {index, pos}; + pos++; + } + return {-1, -1}; +} + +void hashDelete(int key, vector>& table) { + int index = key % SLOT_SIZE; + auto& chain = table[index]; + for (auto it = chain.begin(); it != chain.end(); ++it) { + if (*it == key) { + chain.erase(it); + break; + } + } +} + +int main() { + srand(time(0)); + int dataSize = rand() % 96 + 5; + vector data(dataSize); + vector> hashTable(SLOT_SIZE); + + for (int i = 0; i < dataSize; ++i) { + data[i] = rand() % 1001; + hashInsert(data[i], hashTable); + } + + cout << "Now displaying Chaining Hash" << endl; + cout << "Hash Table:\n"; + for (int i = 0; i < SLOT_SIZE; ++i) { + cout << "Slot " << i << ": "; + for (int val : hashTable[i]) cout << val << " "; + cout << endl; + } + + int target = data[rand() % data.size()]; + auto [slot, pos] = hashSearch(target, hashTable); + if (slot != -1) + cout << "The selected element " << target << " is in Slot " << slot << ", Position " << pos << endl; + else + cout << "The selected element " << target << " was not found in the table." << endl; + + hashDelete(target, hashTable); + + cout << "After Deletion:\n"; + for (int i = 0; i < SLOT_SIZE; ++i) { + cout << "Slot " << i << ": "; + for (int val : hashTable[i]) cout << val << " "; + cout << endl; + } + + return 0; +} diff --git a/C++/Dijkstra.cpp b/C++/Dijkstra.cpp new file mode 100644 index 0000000..43f215b --- /dev/null +++ b/C++/Dijkstra.cpp @@ -0,0 +1,98 @@ +#include +#include +#include +#include +#include + +using namespace std; + +struct Vertex { + string key; + vector> adjacent; + Vertex* prev = nullptr; + + Vertex(string k) : key(k) {} +}; + +class Graph { +public: + unordered_map nodes; + + void addVertex(const string& key) { + if (nodes.find(key) == nodes.end()) { + nodes[key] = new Vertex(key); + } + } + + bool addEdge(const string& u, const string& v, int weight) { + if (nodes.find(u) == nodes.end() || nodes.find(v) == nodes.end()) + throw invalid_argument("Both vertices must exist."); + for (auto& [neighbor, _] : nodes[u]->adjacent) { + if (neighbor->key == v) + return false; // Edge already exists + } + nodes[u]->adjacent.push_back({nodes[v], weight}); + return true; + } + + pair* contains(vector>& lst, Vertex* vertex) { + for (auto& p : lst) { + if (p.first == vertex) + return &p; + } + return nullptr; + } + + vector dijkstra(const string& start_key, const string& end_key) { + vector> open_list = {{nodes[start_key], 0}}; + vector> closed_list; + + _recursion(open_list, closed_list, nodes[end_key]); + + vector path; + Vertex* node = nodes[end_key]; + while (node) { + path.push_back(node); + node = node->prev; + } + reverse(path.begin(), path.end()); + return path; + } + +private: + void _recursion(vector>& open_list, vector>& closed_list, Vertex* end_node) { + if (contains(closed_list, end_node) || open_list.empty()) + return; + + auto current = open_list.front(); + open_list.erase(open_list.begin()); + closed_list.push_back(current); + + Vertex* u = current.first; + int u_dist = current.second; + + for (auto& [neighbor, weight] : u->adjacent) { + if (contains(closed_list, neighbor)) continue; + + auto existing = contains(open_list, neighbor); + int new_dist = u_dist + weight; + + if (existing) { + if (new_dist < existing->second) { + open_list.erase(remove(open_list.begin(), open_list.end(), *existing), open_list.end()); + } else { + continue; + } + } + + neighbor->prev = u; + open_list.push_back({neighbor, new_dist}); + } + + sort(open_list.begin(), open_list.end(), [](auto& a, auto& b) { + return a.second < b.second; + }); + + _recursion(open_list, closed_list, end_node); + } +}; diff --git a/C++/DoubleLinkedList.cpp b/C++/DoubleLinkedList.cpp new file mode 100644 index 0000000..366ebb3 --- /dev/null +++ b/C++/DoubleLinkedList.cpp @@ -0,0 +1,74 @@ +#include +#include + +class DoublyCircularLinkedList { +public: + struct Node { + std::string key; + Node* prev; + Node* next; + + Node(const std::string& k) : key(k), prev(nullptr), next(nullptr) {} + }; + + DoublyCircularLinkedList() { + nil = new Node("NIL"); + nil->next = nil; + nil->prev = nil; + } + + ~DoublyCircularLinkedList() { + Node* current = nil->next; + while (current != nil) { + Node* next = current->next; + delete current; + current = next; + } + delete nil; + } + + void listInsert(Node* node) { + node->next = nil->next; + nil->next->prev = node; + nil->next = node; + node->prev = nil; + } + + Node* listSearch(const std::string& key) { + Node* x = nil->next; + while (x != nil && x->key != key) { + x = x->next; + } + return x; + } + + void listDelete(Node* node) { + if (node == nil) { + std::cout << "Attempted to delete NIL node; skipping." << std::endl; + return; + } + node->prev->next = node->next; + node->next->prev = node->prev; + delete node; + } + + std::string display() { + std::string result; + Node* x = nil->next; + while (x != nil) { + result += x->key + " "; + x = x->next; + } + if (!result.empty()) result.pop_back(); // 去掉最后一个空格 + return result; + } + + Node* createNode(const std::string& key) { + return new Node(key); + } + +private: + Node* nil; +}; + + diff --git a/C++/Fibonacci.cpp b/C++/Fibonacci.cpp new file mode 100644 index 0000000..57f2cc9 --- /dev/null +++ b/C++/Fibonacci.cpp @@ -0,0 +1,78 @@ +#include +#include + +class Fibonacci { +public: + // 朴素递归(指数时间复杂度) + static int naiveFibonacci(int n) { + if (n == 0) return 0; + if (n == 1) return 1; + return naiveFibonacci(n - 1) + naiveFibonacci(n - 2); + } + + // 线性动态规划(O(n)) + static int linearFibonacci(int n) { + if (n == 0) return 0; + if (n == 1) return 1; + + std::vector A(n + 1); + A[0] = 0; + A[1] = 1; + for (int i = 2; i <= n; ++i) { + A[i] = A[i - 1] + A[i - 2]; + } + return A[n]; + } + + // 矩阵乘法 + static std::vector> matrixMultiply(const std::vector>& m1, + const std::vector>& m2) { + int rows = m1.size(); + int cols = m2[0].size(); + int common = m1[0].size(); + std::vector> result(rows, std::vector(cols, 0)); + + for (int i = 0; i < rows; ++i) { + for (int j = 0; j < cols; ++j) { + for (int k = 0; k < common; ++k) { + result[i][j] += m1[i][k] * m2[k][j]; + } + } + } + return result; + } + + // 快速幂递归计算矩阵的 n 次幂 + static std::vector> recursiveSquaring(int n) { + std::vector> base = {{1, 1}, {1, 0}}; + if (n == 0) return {{1, 0}, {0, 1}}; // 单位矩阵 + if (n == 1) return base; + + std::vector> half = recursiveSquaring(n / 2); + std::vector> square = matrixMultiply(half, half); + + if (n % 2 == 0) { + return square; + } else { + return matrixMultiply(square, base); + } + } + + // 对应的 Fibonacci(n) + static int logarithmicFibonacci(int n) { + if (n == 0) return 0; + std::vector> matrix = recursiveSquaring(n); + return matrix[0][1]; + } +}; + +// 测试主函数 +int main() { + int n = 20; + + std::cout << "Naive Fibonacci(" << n << "): " << Fibonacci::naiveFibonacci(n) << std::endl; + std::cout << "Linear Fibonacci(" << n << "): " << Fibonacci::linearFibonacci(n) << std::endl; + std::cout << "Logarithmic Fibonacci(" << n << "): " << Fibonacci::logarithmicFibonacci(n) << std::endl; + + return 0; +} diff --git a/C++/Heapsort.cpp b/C++/Heapsort.cpp new file mode 100644 index 0000000..70a9d1d --- /dev/null +++ b/C++/Heapsort.cpp @@ -0,0 +1,66 @@ +#include +#include +#include // for std::copy +using namespace std; + +class HeapSort { +public: + // 保持最大堆性质 + static void maxHeapify(vector& arr, int i, int heapSize) { + int left = 2 * i + 1; + int right = 2 * i + 2; + int largest = i; + + if (left < heapSize && arr[left] > arr[largest]) { + largest = left; + } + if (right < heapSize && arr[right] > arr[largest]) { + largest = right; + } + + if (largest != i) { + swap(arr[i], arr[largest]); + maxHeapify(arr, largest, heapSize); + } + } + + // 构建最大堆 + static void buildMaxHeap(vector& arr) { + int heapSize = arr.size(); + for (int i = heapSize / 2 - 1; i >= 0; i--) { + maxHeapify(arr, i, heapSize); + } + } + + // 堆排序,返回升序副本 + static vector heapSort(const vector& arr) { + vector sorted = arr; + buildMaxHeap(sorted); + int heapSize = sorted.size(); + + for (int i = sorted.size() - 1; i > 0; i--) { + swap(sorted[0], sorted[i]); + heapSize--; + maxHeapify(sorted, 0, heapSize); + } + return sorted; + } + + // 打印工具 + static void printVector(const vector& vec, const string& label) { + cout << label; + for (int val : vec) { + cout << val << " "; + } + cout << endl; + } +}; + +// 测试主函数 +int main() { + vector data = {23, 1, 45, 78, 3, 5, 9}; + HeapSort::printVector(data, "Original: "); + vector sorted = HeapSort::heapSort(data); + HeapSort::printVector(sorted, "Sorted: "); + return 0; +} diff --git a/C++/InsertionSort.cpp b/C++/InsertionSort.cpp new file mode 100644 index 0000000..a1cfafe --- /dev/null +++ b/C++/InsertionSort.cpp @@ -0,0 +1,51 @@ +#include +#include +#include +#include +#include + +using namespace std; + +class InsertionSort { +public: + // 插入排序:返回升序副本 + static vector insertionSort(const vector& arr) { + vector sorted = arr; // 拷贝原数组 + for (size_t j = 1; j < sorted.size(); ++j) { + int key = sorted[j]; + int i = j - 1; + while (i >= 0 && sorted[i] > key) { + sorted[i + 1] = sorted[i]; + --i; + } + sorted[i + 1] = key; + } + return sorted; + } + + // 打印 vector + static void printVector(const vector& vec, const string& label) { + cout << label; + for (int val : vec) { + cout << val << " "; + } + cout << endl; + } +}; + +// 主函数:测试 +int main() { + srand(time(0)); // 初始化随机种子 + + int size = rand() % 96 + 5; // [5, 100] + vector data(size); + for (int i = 0; i < size; ++i) { + data[i] = rand() % 1001; // [0, 1000] + } + + InsertionSort::printVector(data, "Original array: "); + vector sortedData = InsertionSort::insertionSort(data); + InsertionSort::printVector(sortedData, "Sorted array: "); + + return 0; +} diff --git a/C++/JumpList.cpp b/C++/JumpList.cpp new file mode 100644 index 0000000..e4e1dd1 --- /dev/null +++ b/C++/JumpList.cpp @@ -0,0 +1,164 @@ +#include +#include +#include +#include + +using namespace std; + +struct Node { + int key; + Node* next; + Node* prev; + Node* down; + + Node(int k) : key(k), next(nullptr), prev(nullptr), down(nullptr) {} +}; + +struct LevelList { + Node* head; + Node* tail; + + LevelList() { + head = new Node(-1); // -∞ + tail = new Node(10000); // +∞ + head->next = tail; + tail->prev = head; + } +}; + +class SkipList { +public: + vector levels; + + SkipList() { + levels.push_back(new LevelList()); // Level 0 + srand((unsigned int)time(nullptr)); // 初始化随机种子 + } + + ~SkipList() { + for (LevelList* level : levels) { + Node* current = level->head; + while (current) { + Node* next = current->next; + delete current; + current = next; + } + delete level; + } + } + + void addLevel() { + LevelList* newLevel = new LevelList(); + newLevel->head->down = levels.back()->head; + newLevel->tail->down = levels.back()->tail; + levels.push_back(newLevel); + } + + void insert(int key) { + int level = 0; + while (rand() % 2 == 0) level++; + while ((int)levels.size() <= level) addLevel(); + + Node* newNode = new Node(key); + Node* current = levels[level]->head; + + // 寻找插入位置(最上层) + while (current->next->key < key) { + current = current->next; + } + + // 插入当前层 + newNode->next = current->next; + newNode->prev = current; + current->next->prev = newNode; + current->next = newNode; + + // 向下插入 + insertDown(newNode, newNode->prev->down, key); + } + + void insertDown(Node* upperNode, Node* downNode, int key) { + if (!downNode) return; + + Node* newNode = new Node(key); + upperNode->down = newNode; + + Node* current = downNode; + while (current->next->key < key) { + current = current->next; + } + + newNode->next = current->next; + newNode->prev = current; + current->next->prev = newNode; + current->next = newNode; + + insertDown(newNode, newNode->prev->down, key); + } + + Node* search(int key) { + Node* current = levels.back()->head; + while (current) { + while (current->next && current->next->key <= key) { + current = current->next; + } + if (current->key == key) return current; + current = current->down; + } + return nullptr; + } + + bool deleteKey(int key) { + Node* current = levels.back()->head; + bool found = false; + + while (current) { + while (current->next && current->next->key < key) { + current = current->next; + } + + if (current->next && current->next->key == key) { + Node* target = current->next; + current->next = target->next; + target->next->prev = current; + delete target; + found = true; + current = current->down; + } else { + current = current->down; + } + } + + return found; + } + + void print() { + for (int i = (int)levels.size() - 1; i >= 0; --i) { + Node* current = levels[i]->head; + cout << "Level " << i << ": "; + while (current) { + cout << current->key << " "; + current = current->next; + if (current && current->key == 10000) break; + } + cout << endl; + } + } +}; + +// === 测试主函数 === +int main() { + SkipList sl; + for (int i = 1; i <= 10; ++i) { + sl.insert(i * 10); + } + + sl.print(); + + int key = 50; + cout << "Searching for " << key << ": " << (sl.search(key) != nullptr ? "Found" : "Not found") << endl; + cout << "Deleting " << key << ": " << (sl.deleteKey(key) ? "Deleted" : "Not found") << endl; + sl.print(); + + return 0; +} From 6d7914cb23b7d7c81fdf209bafb4567dab0e8829 Mon Sep 17 00:00:00 2001 From: GaopingZhou Date: Wed, 14 May 2025 02:25:44 +0800 Subject: [PATCH 17/17] Gaoping Zhou from py to JAVA --- JAVA/BinarySearch.java | 26 +++++++ JAVA/BinarySearchTree.java | 91 ++++++++++++++++++++++++ JAVA/Dijkstra.java | 101 +++++++++++++++++++++++++++ JAVA/DoubleLinkedList.java | 62 +++++++++++++++++ JAVA/FibonacciNumber.java | 64 +++++++++++++++++ JAVA/Graph.java | 132 +++++++++++++++++++++++++++++++++++ JAVA/HeapSort.java | 48 +++++++++++++ JAVA/InsertionSort.java | 21 ++++++ JAVA/JumpList.java | 138 +++++++++++++++++++++++++++++++++++++ 9 files changed, 683 insertions(+) create mode 100644 JAVA/BinarySearch.java create mode 100644 JAVA/BinarySearchTree.java create mode 100644 JAVA/Dijkstra.java create mode 100644 JAVA/DoubleLinkedList.java create mode 100644 JAVA/FibonacciNumber.java create mode 100644 JAVA/Graph.java create mode 100644 JAVA/HeapSort.java create mode 100644 JAVA/InsertionSort.java create mode 100644 JAVA/JumpList.java diff --git a/JAVA/BinarySearch.java b/JAVA/BinarySearch.java new file mode 100644 index 0000000..8c942ba --- /dev/null +++ b/JAVA/BinarySearch.java @@ -0,0 +1,26 @@ +import java.util.List; + +public class BinarySearch { + public static List insertionSort(List A) { + for (int j = 1; j < A.size(); j++) { + int key = A.get(j); + int i = j - 1; + while (i >= 0 && A.get(i) > key) { + A.set(i + 1, A.get(i)); + i--; + } + A.set(i + 1, key); + } + return A; + } + + public static int binarySearch(List A, int p, int r, int key) { + while (p <= r) { + int q = (p + r) / 2; + if (A.get(q) == key) return q; + else if (A.get(q) < key) p = q + 1; + else r = q - 1; + } + return -1; + } +} diff --git a/JAVA/BinarySearchTree.java b/JAVA/BinarySearchTree.java new file mode 100644 index 0000000..3c3db8b --- /dev/null +++ b/JAVA/BinarySearchTree.java @@ -0,0 +1,91 @@ + + import java.util.*; + + class TreeNode { + int k; + TreeNode l, r, p; + + TreeNode(int key) { + this.k = key; + this.l = this.r = this.p = null; + } + } + + public class BinarySearchTree { + TreeNode root = null; + + public void insert(int key) { + TreeNode node = new TreeNode(key); + TreeNode y = null; + TreeNode x = root; + + while (x != null) { + y = x; + if (node.k < x.k) + x = x.l; + else + x = x.r; + } + + node.p = y; + if (y == null) + root = node; + else if (node.k < y.k) + y.l = node; + else + y.r = node; + } + + public void inorderWalk(TreeNode node, List result) { + if (node != null) { + inorderWalk(node.l, result); + result.add(node.k); + inorderWalk(node.r, result); + } + } + + public TreeNode search(TreeNode node, int key) { + if (node == null || key == node.k) + return node; + if (key < node.k) + return search(node.l, key); + else + return search(node.r, key); + } + + public TreeNode minimum(TreeNode node) { + while (node.l != null) + node = node.l; + return node; + } + + public void transplant(TreeNode u, TreeNode v) { + if (u.p == null) + root = v; + else if (u == u.p.l) + u.p.l = v; + else + u.p.r = v; + if (v != null) + v.p = u.p; + } + + public void deleteNode(TreeNode z) { + if (z.l == null) { + transplant(z, z.r); + } else if (z.r == null) { + transplant(z, z.l); + } else { + TreeNode y = minimum(z.r); + if (y.p != z) { + transplant(y, y.r); + y.r = z.r; + if (y.r != null) y.r.p = y; + } + transplant(z, y); + y.l = z.l; + if (y.l != null) y.l.p = y; + } + } + } + diff --git a/JAVA/Dijkstra.java b/JAVA/Dijkstra.java new file mode 100644 index 0000000..e54b98f --- /dev/null +++ b/JAVA/Dijkstra.java @@ -0,0 +1,101 @@ + + import java.util.*; + + class Vertex { + String key; + List adjacent = new ArrayList<>(); + Vertex prev = null; + + Vertex(String key) { + this.key = key; + } + + static class Edge { + Vertex neighbor; + int weight; + + Edge(Vertex neighbor, int weight) { + this.neighbor = neighbor; + this.weight = weight; + } + } + } + + public class Dijkstra { + Map nodes = new HashMap<>(); + + public void addVertex(String key) { + nodes.putIfAbsent(key, new Vertex(key)); + } + + public boolean addEdge(String u, String v, int weight) { + if (!nodes.containsKey(u) || !nodes.containsKey(v)) + throw new IllegalArgumentException("Both vertices must exist."); + for (Vertex.Edge e : nodes.get(u).adjacent) { + if (e.neighbor.key.equals(v)) return false; + } + nodes.get(u).adjacent.add(new Vertex.Edge(nodes.get(v), weight)); + return true; + } + + private Vertex.Edge contains(List> lst, Vertex v) { + for (Map.Entry entry : lst) { + if (entry.getKey() == v) + return new Vertex.Edge(entry.getKey(), entry.getValue()); + } + return null; + } + + public List dijkstra(String startKey, String endKey) { + List> openList = new ArrayList<>(); + List> closedList = new ArrayList<>(); + + openList.add(new AbstractMap.SimpleEntry<>(nodes.get(startKey), 0)); + _recursion(openList, closedList, nodes.get(endKey)); + + List path = new ArrayList<>(); + Vertex node = nodes.get(endKey); + while (node != null) { + path.add(node); + node = node.prev; + } + Collections.reverse(path); + return path; + } + + private void _recursion(List> openList, + List> closedList, + Vertex endNode) { + if (contains(closedList, endNode) != null || openList.isEmpty()) + return; + + Map.Entry current = openList.remove(0); + closedList.add(current); + + Vertex u = current.getKey(); + int uDist = current.getValue(); + + for (Vertex.Edge e : u.adjacent) { + Vertex neighbor = e.neighbor; + int weight = e.weight; + + if (contains(closedList, neighbor) != null) continue; + + Vertex.Edge existing = contains(openList, neighbor); + int newDist = uDist + weight; + + if (existing != null) { + if (newDist >= existing.weight) continue; + openList.removeIf(entry -> entry.getKey() == neighbor); + } + + neighbor.prev = u; + openList.add(new AbstractMap.SimpleEntry<>(neighbor, newDist)); + } + + openList.sort(Comparator.comparingInt(Map.Entry::getValue)); + _recursion(openList, closedList, endNode); + } + } + + diff --git a/JAVA/DoubleLinkedList.java b/JAVA/DoubleLinkedList.java new file mode 100644 index 0000000..0aa4a87 --- /dev/null +++ b/JAVA/DoubleLinkedList.java @@ -0,0 +1,62 @@ + + public class DoubleLinkedList { + public DoubleLinkedList(Node nil) { + this.nil = nil; + } + + static class Node { + String key; + Node prev; + Node next; + + Node(String key) { + this.key = key; + this.prev = this.next = null; + } + } + + private Node nil; // Sentinel node + + public void DoublyCircularLinkedList() { + nil = new Node("NIL"); + nil.next = nil; + nil.prev = nil; + } + + public void listInsert(Node node) { + // Insert at the head (right after NIL) + node.next = nil.next; + nil.next.prev = node; + nil.next = node; + node.prev = nil; + } + + public Node listSearch(String key) { + Node x = nil.next; + while (x != nil && !x.key.equals(key)) { + x = x.next; + } + return x; + } + + public void listDelete(Node node) { + if (node == nil) { + System.out.println("Attempted to delete NIL node; skipping."); + return; + } + node.prev.next = node.next; + node.next.prev = node.prev; + } + + public String display() { + StringBuilder sb = new StringBuilder(); + Node x = nil.next; + while (x != nil) { + sb.append(x.key).append(" "); + x = x.next; + } + return sb.toString().trim(); + } + } + + diff --git a/JAVA/FibonacciNumber.java b/JAVA/FibonacciNumber.java new file mode 100644 index 0000000..119b602 --- /dev/null +++ b/JAVA/FibonacciNumber.java @@ -0,0 +1,64 @@ +public class FibonacciNumber { + + + // 递归方式(指数时间复杂度) + public static int naiveFibonacci(int n) { + if (n == 0) return 0; + if (n == 1) return 1; + return naiveFibonacci(n - 1) + naiveFibonacci(n - 2); + } + + // 线性 DP(时间复杂度 O(n)) + public static int linearFibonacci(int n) { + if (n == 0) return 0; + if (n == 1) return 1; + + int[] A = new int[n + 1]; + A[0] = 0; + A[1] = 1; + for (int i = 2; i <= n; i++) { + A[i] = A[i - 1] + A[i - 2]; + } + return A[n]; + } + + // 矩阵乘法 + public static int[][] matrixMultiply(int[][] m1, int[][] m2) { + int rows = m1.length; + int cols = m2[0].length; + int common = m1[0].length; + int[][] result = new int[rows][cols]; + + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + for (int k = 0; k < common; k++) { + result[i][j] += m1[i][k] * m2[k][j]; + } + } + } + return result; + } + + // 快速幂法递归计算矩阵的 n 次幂 + public static int[][] recursiveSquaring(int n) { + int[][] base = {{1, 1}, {1, 0}}; + if (n == 0) return new int[][]{{1, 0}, {0, 1}}; // 单位矩阵 + if (n == 1) return base; + + int[][] half = recursiveSquaring(n / 2); + int[][] square = matrixMultiply(half, half); + + if (n % 2 == 0) { + return square; + } else { + return matrixMultiply(square, base); + } + } + + // 主函数:快速幂法 Fibonacci + public static int logarithmicFibonacci(int n) { + if (n == 0) return 0; + int[][] matrix = recursiveSquaring(n); + return matrix[0][1]; + } +} diff --git a/JAVA/Graph.java b/JAVA/Graph.java new file mode 100644 index 0000000..7f18b49 --- /dev/null +++ b/JAVA/Graph.java @@ -0,0 +1,132 @@ +import java.util.*; + +class Node { + String key; + List adjacent; + + Node(String key) { + this.key = key; + this.adjacent = new ArrayList<>(); + } + + static class Neighbor { + Node node; + int weight; + + Neighbor(Node node, int weight) { + this.node = node; + this.weight = weight; + } + } +} + +public class Graph { + Map nodes = new HashMap<>(); + List openList; + List closedList; + Set visited; + + public void addNode(String key, List neighbors, List weights) { + Node node = new Node(key); + nodes.put(key, node); + + if (neighbors != null) { + if (weights == null) { + weights = new ArrayList<>(Collections.nCopies(neighbors.size(), 1)); + } + + for (int i = 0; i < neighbors.size(); i++) { + String neighborKey = neighbors.get(i); + int weight = weights.get(i); + if (nodes.containsKey(neighborKey)) { + node.adjacent.add(new Node.Neighbor(nodes.get(neighborKey), weight)); + } + } + } + } + + public void addEdge(String u, String v, int weight) { + Node uNode = nodes.get(u); + Node vNode = nodes.get(v); + boolean exists = false; + for (Node.Neighbor neighbor : uNode.adjacent) { + if (neighbor.node.key.equals(v)) { + exists = true; + break; + } + } + if (!exists) { + uNode.adjacent.add(new Node.Neighbor(vNode, weight)); + } + } + + public List bdfs(String startKey, String mode) { + if (!nodes.containsKey(startKey)) return new ArrayList<>(); + + openList = new LinkedList<>(); + closedList = new ArrayList<>(); + visited = new HashSet<>(); + + openList.add(nodes.get(startKey)); + _recurse(mode.toUpperCase()); + + return closedList; + } + + private void _recurse(String mode) { + if (openList.isEmpty()) return; + + Node current = openList.remove(0); + closedList.add(current); + visited.add(current.key); + + for (Node.Neighbor neighbor : current.adjacent) { + if (!visited.contains(neighbor.node.key) && !openList.contains(neighbor.node)) { + if (mode.equals("BFS")) { + openList.add(neighbor.node); + } else if (mode.equals("DFS")) { + openList.add(0, neighbor.node); + } + } + } + + _recurse(mode); + } + + // Optional: Display traversal keys + public static List extractKeys(List nodeList) { + List keys = new ArrayList<>(); + for (Node n : nodeList) { + keys.add(n.key); + } + return keys; + } + + // === 示例测试 === + public static void main(String[] args) { + Graph graph = new Graph(); + + // Add nodes + graph.addNode("A", null, null); + graph.addNode("B", null, null); + graph.addNode("C", null, null); + graph.addNode("D", null, null); + graph.addNode("E", null, null); + + // Add edges + graph.addEdge("A", "B", 1); + graph.addEdge("A", "C", 1); + graph.addEdge("B", "D", 1); + graph.addEdge("C", "E", 1); + + // BFS traversal + List bfsResult = graph.bdfs("A", "BFS"); + System.out.println("BFS: " + extractKeys(bfsResult)); + + // DFS traversal + List dfsResult = graph.bdfs("A", "DFS"); + System.out.println("DFS: " + extractKeys(dfsResult)); + } +} + + diff --git a/JAVA/HeapSort.java b/JAVA/HeapSort.java new file mode 100644 index 0000000..a323089 --- /dev/null +++ b/JAVA/HeapSort.java @@ -0,0 +1,48 @@ +import java.util.Arrays; + +public class HeapSort { + + // 保持最大堆性质 + public static void maxHeapify(int[] arr, int i, int heapSize) { + int left = 2 * i + 1; + int right = 2 * i + 2; + int largest = i; + + if (left < heapSize && arr[left] > arr[largest]) { + largest = left; + } + if (right < heapSize && arr[right] > arr[largest]) { + largest = right; + } + + if (largest != i) { + int temp = arr[i]; + arr[i] = arr[largest]; + arr[largest] = temp; + maxHeapify(arr, largest, heapSize); + } + } + + // 构建最大堆 + public static void buildMaxHeap(int[] arr) { + int heapSize = arr.length; + for (int i = (heapSize / 2) - 1; i >= 0; i--) { + maxHeapify(arr, i, heapSize); + } + } + + // 堆排序:返回升序副本 + public static int[] heapSort(int[] arr) { + int[] sorted = Arrays.copyOf(arr, arr.length); + buildMaxHeap(sorted); + int heapSize = sorted.length; + for (int i = sorted.length - 1; i > 0; i--) { + int temp = sorted[0]; + sorted[0] = sorted[i]; + sorted[i] = temp; + heapSize--; + maxHeapify(sorted, 0, heapSize); + } + return sorted; + } +} \ No newline at end of file diff --git a/JAVA/InsertionSort.java b/JAVA/InsertionSort.java new file mode 100644 index 0000000..cdbc629 --- /dev/null +++ b/JAVA/InsertionSort.java @@ -0,0 +1,21 @@ +import java.util.Arrays; +import java.util.Random; + +public class InsertionSort { + + // 插入排序:返回升序副本 + public static int[] insertionSort(int[] arr) { + int[] sorted = Arrays.copyOf(arr, arr.length); // 拷贝原数组 + for (int j = 1; j < sorted.length; j++) { + int key = sorted[j]; + int i = j - 1; + // 将 key 插入到 sorted[0...j-1] 的有序子序列中 + while (i >= 0 && sorted[i] > key) { + sorted[i + 1] = sorted[i]; + i--; + } + sorted[i + 1] = key; + } + return sorted; + } +} diff --git a/JAVA/JumpList.java b/JAVA/JumpList.java new file mode 100644 index 0000000..2a9c14b --- /dev/null +++ b/JAVA/JumpList.java @@ -0,0 +1,138 @@ +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +class Node { + int key; + Node next; + Node prev; + Node down; + + Node(int key) { + this.key = key; + this.next = null; + this.prev = null; + this.down = null; + } +} + +class LevelList { + Node head; + Node tail; + + LevelList() { + head = new Node(-1); // -∞ sentinel + tail = new Node(10000); // +∞ sentinel + head.next = tail; + tail.prev = head; + } +} + +public class JumpList { + List levels; + Random rand; + + public JumpList() { + levels = new ArrayList<>(); + levels.add(new LevelList()); // Level 0 + rand = new Random(); + } + + public void addLevel() { + LevelList newLevel = new LevelList(); + newLevel.head.down = levels.get(levels.size() - 1).head; + newLevel.tail.down = levels.get(levels.size() - 1).tail; + levels.add(newLevel); + } + + public void insert(int key) { + int level = 0; + while (rand.nextInt(2) == 0) level++; + while (levels.size() <= level) addLevel(); + + Node newNode = new Node(key); + Node current = levels.get(level).head; + + // Find insert position on top level + while (current.next.key < key) { + current = current.next; + } + + // Insert node + newNode.next = current.next; + newNode.prev = current; + current.next.prev = newNode; + current.next = newNode; + + // Insert downward recursively + insertDown(newNode, newNode.prev.down, key); + } + + private void insertDown(Node upperNode, Node downNode, int key) { + if (downNode == null) return; + + Node newNode = new Node(key); + upperNode.down = newNode; + + Node current = downNode; + while (current.next.key < key) { + current = current.next; + } + + newNode.next = current.next; + newNode.prev = current; + current.next.prev = newNode; + current.next = newNode; + + insertDown(newNode, newNode.prev.down, key); + } + + public Node search(int key) { + Node current = levels.get(levels.size() - 1).head; + while (current != null) { + while (current.next != null && current.next.key <= key) { + current = current.next; + } + if (current.key == key) return current; + current = current.down; + } + return null; + } + + public boolean delete(int key) { + Node current = levels.get(levels.size() - 1).head; + boolean found = false; + + while (current != null) { + while (current.next != null && current.next.key < key) { + current = current.next; + } + + if (current.next != null && current.next.key == key) { + Node target = current.next; + current.next = target.next; + target.next.prev = current; + found = true; + current = current.down; + } else { + current = current.down; + } + } + + return found; + } + + // Optional: print skip list from top to bottom + public void print() { + for (int i = levels.size() - 1; i >= 0; i--) { + Node current = levels.get(i).head; + System.out.print("Level " + i + ": "); + while (current != null) { + System.out.print(current.key + " "); + current = current.next; + if (current != null && current.key == 10000) break; + } + System.out.println(); + } + } +} \ No newline at end of file