- 区块链的概念及特点
- 区块链的学习路径
- 区块链共识算法
- 进程、线程、内存管理
- 网络通信协议、TCP/IP、UDP、网络拓扑
- 数据结构链表、哈希表、图、树、搜索算法(Python)
- 数据结构链表、哈希表、图、树、搜索算法(C语言)
数据结构链表、哈希表、图、树、搜索算法(Python)
class 数据结构,链表,图,树,搜索算法,排序数据结构和算法是计算机科学的核心基础,理解这些概念和它们的实现对于高效软件开发至关重要。在本指南中,我们将详细介绍链表、树、图、哈希表、排序和搜索算法,包括它们的理论基础和 Python 代码实现。
1. 链表(Linked List)
理论
链表是一种线性数据结构,由节点组成。每个节点包含数据部分和指向下一个节点的指针。链表分为以下几种类型:
- 单链表(Singly Linked List): 每个节点只指向下一个节点。
- 双链表(Doubly Linked List): 每个节点有两个指针,分别指向前一个和后一个节点。
- 循环链表(Circular Linked List): 最后一个节点指向第一个节点,形成一个环。
单链表的实现
以下是单链表的基本实现,包括插入、删除、搜索等操作:
class Node:
def __init__(self, data):
self.data = data
self.next = None
class SinglyLinkedList:
def __init__(self):
self.head = None
def insert_at_beginning(self, data):
new_node = Node(data)
new_node.next = self.head
self.head = new_node
def insert_at_end(self, data):
new_node = Node(data)
if not self.head:
self.head = new_node
return
last_node = self.head
while last_node.next:
last_node = last_node.next
last_node.next = new_node
def delete_node(self, key):
current_node = self.head
# 删除头节点
if current_node and current_node.data == key:
self.head = current_node.next
current_node = None
return
# 删除非头节点
prev_node = None
while current_node and current_node.data != key:
prev_node = current_node
current_node = current_node.next
if current_node is None:
return
prev_node.next = current_node.next
current_node = None
def search(self, key):
current_node = self.head
while current_node:
if current_node.data == key:
return True
current_node = current_node.next
return False
def display(self):
current_node = self.head
elements = []
while current_node:
elements.append(current_node.data)
current_node = current_node.next
return elements
# 使用示例
linked_list = SinglyLinkedList()
linked_list.insert_at_beginning(3)
linked_list.insert_at_beginning(2)
linked_list.insert_at_end(4)
linked_list.insert_at_end(5)
linked_list.delete_node(3)
print("链表内容:", linked_list.display()) # 输出: [2, 4, 5]
print("搜索 4:", linked_list.search(4)) # 输出: True
print("搜索 3:", linked_list.search(3)) # 输出: False
双链表的实现
双链表的实现如下:
class DNode:
def __init__(self, data):
self.data = data
self.prev = None
self.next = None
class DoublyLinkedList:
def __init__(self):
self.head = None
def insert_at_beginning(self, data):
new_node = DNode(data)
new_node.next = self.head
if self.head:
self.head.prev = new_node
self.head = new_node
def insert_at_end(self, data):
new_node = DNode(data)
if not self.head:
self.head = new_node
return
last_node = self.head
while last_node.next:
last_node = last_node.next
last_node.next = new_node
new_node.prev = last_node
def delete_node(self, key):
current_node = self.head
# 删除头节点
if current_node and current_node.data == key:
self.head = current_node.next
if self.head:
self.head.prev = None
current_node = None
return
# 删除非头节点
while current_node and current_node.data != key:
current_node = current_node.next
if current_node is None:
return
if current_node.next:
current_node.next.prev = current_node.prev
if current_node.prev:
current_node.prev.next = current_node.next
current_node = None
def display(self):
current_node = self.head
elements = []
while current_node:
elements.append(current_node.data)
current_node = current_node.next
return elements
# 使用示例
doubly_linked_list = DoublyLinkedList()
doubly_linked_list.insert_at_beginning(3)
doubly_linked_list.insert_at_beginning(2)
doubly_linked_list.insert_at_end(4)
doubly_linked_list.insert_at_end(5)
doubly_linked_list.delete_node(3)
print("双链表内容:", doubly_linked_list.display()) # 输出: [2, 4, 5]
2. 树(Tree)
理论
树是一种分层数据结构,由节点组成。它的特点是每个节点有零个或多个子节点,且没有循环。树结构广泛用于组织数据、实现高效查找、插入、删除操作。
- 二叉树(Binary Tree): 每个节点最多有两个子节点(左子节点和右子节点)。
- 二叉搜索树(Binary Search Tree, BST): 每个节点的左子树包含的值小于该节点的值,右子树包含的值大于该节点的值。
- 平衡树(Balanced Tree): 通过各种机制(如 AVL 树、红黑树)保持树的高度平衡,确保高效操作。
二叉树的实现
以下是一个简单的二叉树实现,包括插入和遍历操作:
class TreeNode:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
class BinaryTree:
def __init__(self):
self.root = None
def insert(self, data):
if not self.root:
self.root = TreeNode(data)
else:
self._insert_recursively(self.root, data)
def _insert_recursively(self, node, data):
if data < node.data:
if node.left is None:
node.left = TreeNode(data)
else:
self._insert_recursively(node.left, data)
else:
if node.right is None:
node.right = TreeNode(data)
else:
self._insert_recursively(node.right, data)
def inorder_traversal(self, node):
if node:
self.inorder_traversal(node.left)
print(node.data, end=' ')
self.inorder_traversal(node.right)
def preorder_traversal(self, node):
if node:
print(node.data, end=' ')
self.preorder_traversal(node.left)
self.preorder_traversal(node.right)
def postorder_traversal(self, node):
if node:
self.postorder_traversal(node.left)
self.postorder_traversal(node.right)
print(node.data, end=' ')
# 使用示例
binary_tree = BinaryTree()
binary_tree.insert(5)
binary_tree.insert(3)
binary_tree.insert(7)
binary_tree.insert(2)
binary_tree.insert(4)
binary_tree.insert(6)
binary_tree.insert(8)
print("中序遍历:", end=' ')
binary_tree.inorder_traversal(binary_tree.root) # 输出: 2 3 4 5 6 7 8
print("\n前序遍历:", end=' ')
binary_tree.preorder_traversal(binary_tree.root) # 输出: 5 3 2 4 7 6 8
print("\n后序遍历:", end=' ')
binary_tree.postorder_traversal(binary_tree.root) # 输出: 2 4 3 6 8 7 5
二叉搜索树的实现
以下是一个简单的二叉搜索树实现,包括插入、搜索和删除操作:
class TreeNode:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
class BinarySearchTree:
def __init__(self):
self.root = None
def insert(self, data):
if not self.root:
self.root = TreeNode(data)
else:
self._insert_recursively(self.root, data)
def _insert_recursively(self, node, data):
if data < node.data:
if node.left is None:
node.left = TreeNode(data)
else:
self._insert_recursively(node.left, data)
else:
if node.right is None:
node.right = TreeNode(data)
else:
self._insert_recursively(node.right, data)
def search(self, data):
return self._search_recursively(self.root, data)
def _search_recursively(self, node, data):
if node is None or node.data == data:
return node
if data < node.data:
return self
._search_recursively(node.left, data)
return self._search_recursively(node.right, data)
def delete(self, data):
self.root = self._delete_recursively(self.root, data)
def _delete_recursively(self, node, data):
if node is None:
return node
if data < node.data:
node.left = self._delete_recursively(node.left, data)
elif data > node.data:
node.right = self._delete_recursively(node.right, data)
else:
# 节点有一个或没有子节点
if node.left is None:
return node.right
elif node.right is None:
return node.left
# 节点有两个子节点
min_larger_node = self._find_min(node.right)
node.data = min_larger_node.data
node.right = self._delete_recursively(node.right, min_larger_node.data)
return node
def _find_min(self, node):
current_node = node
while current_node.left:
current_node = current_node.left
return current_node
def inorder_traversal(self, node):
if node:
self.inorder_traversal(node.left)
print(node.data, end=' ')
self.inorder_traversal(node.right)
# 使用示例
bst = BinarySearchTree()
bst.insert(5)
bst.insert(3)
bst.insert(7)
bst.insert(2)
bst.insert(4)
bst.insert(6)
bst.insert(8)
print("中序遍历:", end=' ')
bst.inorder_traversal(bst.root) # 输出: 2 3 4 5 6 7 8
print("\n搜索 4:", bst.search(4)) # 输出: <__main__.TreeNode object at ...>
print("搜索 9:", bst.search(9)) # 输出: None
bst.delete(4)
print("删除 4 后中序遍历:", end=' ')
bst.inorder_traversal(bst.root) # 输出: 2 3 5 6 7 8
3. 图(Graph)
理论
图是一种非线性数据结构,由顶点(节点)和边组成。图可以是有向的或无向的,也可以是加权的或无权的。图在建模网络结构(如社交网络、交通网络)中非常有用。
- 有向图(Directed Graph): 边有方向,表示从一个顶点指向另一个顶点。
- 无向图(Undirected Graph): 边无方向,表示两个顶点之间的连接。
- 加权图(Weighted Graph): 边具有权重,表示两个顶点之间的代价或距离。
图的实现
图的实现通常使用邻接表或邻接矩阵。以下是基于邻接表的简单图实现,包括深度优先搜索(DFS)和广度优先搜索(BFS):
class Graph:
def __init__(self):
self.adjacency_list = {}
def add_vertex(self, vertex):
if vertex not in self.adjacency_list:
self.adjacency_list[vertex] = []
def add_edge(self, vertex1, vertex2):
if vertex1 in self.adjacency_list and vertex2 in self.adjacency_list:
self.adjacency_list[vertex1].append(vertex2)
self.adjacency_list[vertex2].append(vertex1)
def dfs(self, start_vertex, visited=None):
if visited is None:
visited = set()
visited.add(start_vertex)
print(start_vertex, end=' ')
for neighbor in self.adjacency_list[start_vertex]:
if neighbor not in visited:
self.dfs(neighbor, visited)
def bfs(self, start_vertex):
visited = set()
queue = [start_vertex]
visited.add(start_vertex)
while queue:
vertex = queue.pop(0)
print(vertex, end=' ')
for neighbor in self.adjacency_list[vertex]:
if neighbor not in visited:
queue.append(neighbor)
visited.add(neighbor)
# 使用示例
graph = Graph()
graph.add_vertex('A')
graph.add_vertex('B')
graph.add_vertex('C')
graph.add_vertex('D')
graph.add_vertex('E')
graph.add_edge('A', 'B')
graph.add_edge('A', 'C')
graph.add_edge('B', 'D')
graph.add_edge('C', 'E')
print("深度优先搜索:", end=' ')
graph.dfs('A') # 输出: A B D C E
print("\n广度优先搜索:", end=' ')
graph.bfs('A') # 输出: A B C D E
4. 哈希表(Hash Table)
理论
哈希表是一种通过哈希函数实现快速查找的数据结构。它将键映射到值,支持常数时间复杂度的插入、删除和查找操作。
- 哈希函数(Hash Function): 将输入(键)转换为固定大小的整数(哈希值)。
- 冲突(Collision): 不同的键映射到相同的哈希值时发生冲突。
- 解决冲突的方法:
- 链地址法(Chaining): 每个桶中保存一个链表来存储冲突的键值对。
- 开放地址法(Open Addressing): 冲突时寻找下一个空闲位置。
哈希表的实现
以下是基于链地址法的简单哈希表实现:
class HashTable:
def __init__(self, size):
self.size = size
self.table = [[] for _ in range(size)]
def _hash_function(self, key):
return hash(key) % self.size
def insert(self, key, value):
index = self._hash_function(key)
for pair in self.table[index]:
if pair[0] == key:
pair[1] = value
return
self.table[index].append([key, value])
def search(self, key):
index = self._hash_function(key)
for pair in self.table[index]:
if pair[0] == key:
return pair[1]
return None
def delete(self, key):
index = self._hash_function(key)
for i, pair in enumerate(self.table[index]):
if pair[0] == key:
del self.table[index][i]
return
# 使用示例
hash_table = HashTable(10)
hash_table.insert('apple', 1)
hash_table.insert('banana', 2)
hash_table.insert('orange', 3)
print("搜索 'apple':", hash_table.search('apple')) # 输出: 1
print("搜索 'banana':", hash_table.search('banana')) # 输出: 2
hash_table.delete('apple')
print("删除 'apple' 后搜索 'apple':", hash_table.search('apple')) # 输出: None
5. 排序算法
排序算法用于将数据按特定顺序排列。常见的排序算法包括冒泡排序、选择排序、插入排序、快速排序和归并排序等。
冒泡排序(Bubble Sort)
冒泡排序是一种简单的交换排序算法,反复比较相邻元素并交换。
def bubble_sort(arr):
n = len(arr)
for i in range(n):
for j in range(0, n - i - 1):
if arr[j] > arr[j + 1]:
arr[j], arr[j + 1] = arr[j + 1], arr[j]
# 使用示例
arr = [64, 34, 25, 12, 22, 11, 90]
bubble_sort(arr)
print("冒泡排序结果:", arr) # 输出: [11, 12, 22, 25, 34, 64, 90]
选择排序(Selection Sort)
选择排序是一种简单的选择排序算法,每次从未排序部分选择最小(或最大)元素并放到排序部分的末尾。
def selection_sort(arr):
n = len(arr)
for i in range(n):
min_idx = i
for j in range(i + 1, n):
if arr[j] < arr[min_idx]:
min_idx = j
arr[i], arr[min_idx] = arr[min_idx], arr[i]
# 使用示例
arr = [64, 25, 12, 22, 11]
selection_sort(arr)
print("选择排序结果:", arr) # 输出: [11, 12, 22, 25, 64]
插入排序(Insertion Sort)
插入排序是一种简单的插入排序算法,每次将一个元素插入到已经排序好的部分中。
def insertion_sort(arr):
for i in range(1, len(arr)):
key = arr[i]
j = i - 1
while j >= 0 and key < arr[j]:
arr[j + 1] = arr[j]
j -= 1
arr[j + 1] = key
# 使用示例
arr = [12, 11, 13, 5, 6]
insertion_sort(arr)
print("插入排序结果:", arr
) # 输出: [5, 6, 11, 12, 13]
快速排序(Quick Sort)
快速排序是一种分治排序算法,通过选择一个基准(pivot)将数组分为左右两部分,然后递归排序。
def quick_sort(arr):
if len(arr) <= 1:
return arr
pivot = arr[len(arr) // 2]
left = [x for x in arr if x < pivot]
middle = [x for x in arr if x == pivot]
right = [x for x in arr if x > pivot]
return quick_sort(left) + middle + quick_sort(right)
# 使用示例
arr = [10, 7, 8, 9, 1, 5]
sorted_arr = quick_sort(arr)
print("快速排序结果:", sorted_arr) # 输出: [1, 5, 7, 8, 9, 10]
归并排序(Merge Sort)
归并排序是一种分治排序算法,将数组分为两半,分别排序后合并。
def merge_sort(arr):
if len(arr) <= 1:
return arr
def merge(left, right):
result = []
i = j = 0
while i < len(left) and j < len(right):
if left[i] < right[j]:
result.append(left[i])
i += 1
else:
result.append(right[j])
j += 1
result.extend(left[i:])
result.extend(right[j:])
return result
mid = len(arr) // 2
left = merge_sort(arr[:mid])
right = merge_sort(arr[mid:])
return merge(left, right)
# 使用示例
arr = [12, 11, 13, 5, 6, 7]
sorted_arr = merge_sort(arr)
print("归并排序结果:", sorted_arr) # 输出: [5, 6, 7, 11, 12, 13]
6. 搜索算法
搜索算法用于在数据结构中查找元素。常见的搜索算法包括线性搜索和二分搜索。
线性搜索(Linear Search)
线性搜索是一种简单的搜索算法,从头到尾逐一比较。
def linear_search(arr, target):
for i, element in enumerate(arr):
if element == target:
return i
return -1
# 使用示例
arr = [2, 3, 4, 10, 40]
target = 10
result = linear_search(arr, target)
print("线性搜索结果:", result) # 输出: 3
二分搜索(Binary Search)
二分搜索是一种高效的搜索算法,适用于已排序数组,通过每次将搜索范围减半来查找元素。
def binary_search(arr, target):
left, right = 0, len(arr) - 1
while left <= right:
mid = left + (right - left) // 2
if arr[mid] == target:
return mid
elif arr[mid] < target:
left = mid + 1
else:
right = mid - 1
return -1
# 使用示例
arr = [2, 3, 4, 10, 40]
target = 10
result = binary_search(arr, target)
print("二分搜索结果:", result) # 输出: 3
总结
在本指南中,我们详细介绍了链表、树、图、哈希表、排序和搜索算法的理论和实现。这些数据结构和算法是软件开发的基础,理解它们的工作原理和应用场景对于编写高效程序至关重要。通过这些示例代码,你可以更好地理解每种数据结构和算法的实现细节,并在实践中应用它们。