本文介绍了算法与数据结构的基本概念和类型,包括搜索、排序、动态规划等算法以及数组、链表、树、图等数据结构。此外,文章深入讲解了高级数据结构如哈希表、堆和并查集的应用场景和实现方法。通过示例代码和实战演练,帮助读者加深对算法与数据结构高级应用的理解。
算法入门基础算法是一系列定义清晰的指令集合,用于解决特定问题或执行特定任务。算法通常分为多个步骤,每个步骤都是可执行的操作。算法需要描述输入和输出,以及如何从输入转换到输出。
常见的算法类型包括以下几种:
时间复杂度是指算法执行所需的时间与输入大小的关系。通常用大O符号表示,如O(n)表示线性时间复杂度,O(n^2)表示二次时间复杂度。空间复杂度是指算法执行所需的空间与输入大小的关系,同样用大O符号表示。
def linear_search(arr, target): # 时间复杂度: O(n) for i in range(len(arr)): if arr[i] == target: return i return -1 def fibonacci(n): # 时间复杂度: O(2^n) (未经优化) if n <= 1: return n return fibonacci(n-1) + fibonacci(n-2) def factorial(n): # 空间复杂度: O(1) result = 1 for i in range(1, n+1): result *= i return result数据结构基础
常见的数据结构包括以下几种:
数组是固定大小的元素集合,每个元素都可以通过索引快速访问。数组的索引从0开始。
# 数组操作 arr = [1, 2, 3, 4, 5] print(arr[2]) # 输出3 arr.append(6) print(arr) # 输出[1, 2, 3, 4, 5, 6]
链表是由一系列节点组成的数据集合,每个节点包含数据和指向下一个节点的指针。链表可以分为单链表、双链表等。
class Node: def __init__(self, data): self.data = data self.next = None class LinkedList: def __init__(self): self.head = None def append(self, data): new_node = Node(data) if not self.head: self.head = new_node return last = self.head while last.next: last = last.next last.next = new_node def print_list(self): current = self.head while current: print(current.data) current = current.next linked_list = LinkedList() linked_list.append(1) linked_list.append(2) linked_list.append(3) linked_list.print_list()
栈是后进先出(LIFO)的数据集合。适用于需要先处理最后添加的数据问题,如函数调用栈和括号匹配。
class Stack: def __init__(self): self.items = [] def is_empty(self): return len(self.items) == 0 def push(self, item): self.items.append(item) def pop(self): if not self.is_empty(): return self.items.pop() def peek(self): if not self.is_empty(): return self.items[-1] def size(self): return len(self.items) stack = Stack() stack.push(1) stack.push(2) print(stack.pop()) # 输出2
队列是先进先出(FIFO)的数据集合。适用于需要先处理最早添加的数据问题,如任务调度和消息队列。
from collections import deque queue = deque() queue.append(1) queue.append(2) print(queue.popleft()) # 输出1常用排序算法详解
冒泡排序通过比较相邻元素,将较大的元素逐渐“冒泡”到数组的末尾。
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] return arr arr = [64, 34, 25, 12, 22, 11, 90] print(bubble_sort(arr)) # 输出[11, 12, 22, 25, 34, 64, 90]
选择排序通过每次选择最小(或最大)的元素,将其放到已排序数组的末尾。
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] return arr arr = [64, 34, 25, 12, 22, 11, 90] print(selection_sort(arr)) # 输出[11, 12, 22, 25, 34, 64, 90]
插入排序通过将未排序的部分逐个插入到已排序部分的适当位置。
def insertion_sort(arr): n = len(arr) for i in range(1, n): key = arr[i] j = i - 1 while j >= 0 and arr[j] > key: arr[j+1] = arr[j] j -= 1 arr[j+1] = key return arr arr = [64, 34, 25, 12, 22, 11, 90] print(insertion_sort(arr)) # 输出[11, 12, 22, 25, 34, 64, 90]
快速排序通过选择一个“基准”元素,将数组分成两部分,其中一部分的所有元素都比基准小,另一部分的所有元素都比基准大,然后递归地对这两部分进行排序。
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 = [64, 34, 25, 12, 22, 11, 90] print(quick_sort(arr)) # 输出[11, 12, 22, 25, 34, 64, 90]树与图的基本概念
树是一种非线性的数据结构,包含节点和边。每个节点都有一个唯一的父节点,除了根节点没有父节点。每个节点可以有零个或多个子节点。
树在计算机科学中有广泛的应用,如文件系统、数据库索引、树形菜单等。
class TreeNode: def __init__(self, value): self.value = value self.children = [] def add_child(self, child_node): self.children.append(child_node) def traverse(self): print(self.value) for child in self.children: child.traverse() root = TreeNode('A') root.add_child(TreeNode('B')) root.add_child(TreeNode('C')) root.children[0].add_child(TreeNode('D')) root.children[0].add_child(TreeNode('E')) root.traverse() # 输出A B D E C
二叉树是一种每个节点最多有两个子节点的树。二叉树可以是普通的二叉树,也可以是平衡的二叉树(如AVL树)。
AVL树是一种自平衡二叉搜索树。每个节点的左子树和右子树的高度差不超过1。
class AVLNode: def __init__(self, value): self.value = value self.left = None self.right = None self.height = 1 class AVLTree: def insert(self, root, value): if not root: return AVLNode(value) elif value < root.value: root.left = self.insert(root.left, value) else: root.right = self.insert(root.right, value) root.height = 1 + max(self.get_height(root.left), self.get_height(root.right)) balance = self.get_balance(root) if balance > 1 and value < root.left.value: return self.right_rotate(root) if balance < -1 and value > root.right.value: return self.left_rotate(root) if balance > 1 and value > root.left.value: root.left = self.left_rotate(root.left) return self.right_rotate(root) if balance < -1 and value < root.right.value: root.right = self.right_rotate(root.right) return self.left_rotate(root) return root def left_rotate(self, z): y = z.right T2 = y.left y.left = z z.right = T2 z.height = 1 + max(self.get_height(z.left), self.get_height(z.right)) y.height = 1 + max(self.get_height(y.left), self.get_height(y.right)) return y def right_rotate(self, z): y = z.left T3 = y.right y.right = z z.left = T3 z.height = 1 + max(self.get_height(z.left), self.get_height(z.right)) y.height = 1 + max(self.get_height(y.left), self.get_height(y.right)) return y def get_height(self, root): if not root: return 0 return root.height def get_balance(self, root): if not root: return 0 return self.get_height(root.left) - self.get_height(root.right) avl_tree = AVLTree() root = None values = [9, 5, 10, 0, 6, 11, -1, 1, 2] for value in values: root = avl_tree.insert(root, value)
图是由节点和边组成的数据结构,节点代表对象,边代表对象之间的关系。图可以是有向的或无向的,可以是加权的或非加权的。
图在计算机科学中有广泛的应用,如社交网络、路由算法和网络流量控制等。
class Graph: def __init__(self): self.graph = {} def add_vertex(self, vertex): if vertex not in self.graph: self.graph[vertex] = [] def add_edge(self, vertex1, vertex2): if vertex1 in self.graph: self.graph[vertex1].append(vertex2) if vertex2 in self.graph: self.graph[vertex2].append(vertex1) def bfs(self, start_vertex): visited = set() queue = [start_vertex] while queue: vertex = queue.pop(0) if vertex not in visited: visited.add(vertex) for neighbor in self.graph[vertex]: if neighbor not in visited: queue.append(neighbor) return visited def dfs(self, start_vertex): visited = set() stack = [start_vertex] while stack: vertex = stack.pop() if vertex not in visited: visited.add(vertex) for neighbor in self.graph[vertex]: if neighbor not in visited: stack.append(neighbor) return visited graph = Graph() graph.add_vertex('A') graph.add_vertex('B') graph.add_vertex('C') graph.add_vertex('D') graph.add_edge('A', 'B') graph.add_edge('B', 'C') graph.add_edge('C', 'D') graph.add_edge('D', 'A') print(graph.bfs('A')) # 输出{'A', 'B', 'C', 'D'} print(graph.dfs('A')) # 输出{'A', 'B', 'C', 'D'}高级数据结构介绍
哈希表是一种通过哈希函数将键映射到数组索引的数据结构。哈希函数将键转换为固定大小的数值,以便在数组中进行快速查找。
散列冲突是指不同的键通过哈希函数映射到相同的索引位置。解决散列冲突的方法有链地址法和开放地址法。
class HashTable: def __init__(self): self.size = 10 self.keys = [None] * self.size self.values = [None] * self.size def _hash(self, key): hash_sum = 0 for char in key: hash_sum += ord(char) return hash_sum % self.size def set(self, key, value): index = self._hash(key) while self.keys[index] is not None: if self.keys[index] == key: self.values[index] = value return index = (index + 1) % self.size self.keys[index] = key self.values[index] = value def get(self, key): index = self._hash(key) while self.keys[index] is not None: if self.keys[index] == key: return self.values[index] index = (index + 1) % self.size return None hash_table = HashTable() hash_table.set('apple', 10) hash_table.set('banana', 20) print(hash_table.get('apple')) # 输出10 print(hash_table.get('banana')) # 输出20
堆是一种特殊的树形数据结构,通常用于实现优先队列。堆可以是最大堆(根节点大于所有子节点)或最小堆(根节点小于所有子节点)。
堆的插入操作通过将新元素插入到堆的末尾,然后上浮到适当位置。堆的删除操作通过将根节点元素替换为堆的最后一个元素,然后下沉到适当位置。
class MinHeap: def __init__(self): self.heap = [] def insert(self, value): self.heap.append(value) self._percolate_up(len(self.heap) - 1) def extract_min(self): if len(self.heap) > 1: self.heap[0], self.heap[-1] = self.heap[-1], self.heap[0] min_value = self.heap.pop() self._percolate_down(0) elif len(self.heap) == 1: min_value = self.heap.pop() else: return None return min_value def _percolate_up(self, index): parent = (index - 1) // 2 while parent >= 0 and self.heap[parent] > self.heap[index]: self.heap[parent], self.heap[index] = self.heap[index], self.heap[parent] index = parent parent = (index - 1) // 2 def _percolate_down(self, index): child = 2 * index + 1 while child < len(self.heap): min_child = child if child + 1 < len(self.heap) and self.heap[child + 1] < self.heap[child]: min_child = child + 1 if self.heap[index] > self.heap[min_child]: self.heap[index], self.heap[min_child] = self.heap[min_child], self.heap[index] index = min_child child = 2 * index + 1 else: break min_heap = MinHeap() min_heap.insert(10) min_heap.insert(5) min_heap.insert(15) min_heap.insert(3) print(min_heap.extract_min()) # 输出3 print(min_heap.extract_min()) # 输出5
并查集是一种用于处理不相交集合的数据结构,支持合并集合和查找元素所属集合的操作。
并查集常用于解决图的连通性问题,如检测图中是否存在环,或检查两个节点是否连通。
class UnionFind: def __init__(self, n): self.parent = [i for i in range(n)] def find(self, x): if self.parent[x] != x: self.parent[x] = self.find(self.parent[x]) return self.parent[x] def union(self, x, y): root_x = self.find(x) root_y = self.find(y) if root_x != root_y: self.parent[root_x] = root_y union_find = UnionFind(6) union_find.union(0, 1) union_find.union(1, 2) union_find.union(3, 4) print(union_find.find(0) == union_find.find(2)) # 输出True print(union_find.find(0) == union_find.find(3)) # 输出False实战演练与常见问题解析
经典算法与数据结构题目包括但不限于:
def find_two_sum(nums, target): complement_map = {} for i, num in enumerate(nums): complement = target - num if complement in complement_map: return [complement_map[complement], i] complement_map[num] = i return [] nums = [2, 7, 11, 15] target = 9 print(find_two_sum(nums, target)) # 输出[0, 1] def longest_common_subsequence(s1, s2): m, n = len(s1), len(s2) dp = [[0] * (n + 1) for _ in range(m + 1)] for i in range(1, m + 1): for j in range(1, n + 1): if s1[i - 1] == s2[j - 1]: dp[i][j] = dp[i - 1][j - 1] + 1 else: dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) return dp[m][n] s1 = "abcde" s2 = "ace" print(longest_common_subsequence(s1, s2)) # 输出3
提高算法与数据结构的理解与应用能力可以通过以下方法:
def reverse_string(s): return s[::-1] def reverse_words(s): return ' '.join(reverse_string(word) for word in s.split()) s = "Hello World" print(reverse_string(s)) # 输出"olleH" print(reverse_words(s)) # 输出"olleH dlroW"
通过以上的讲解和示例代码,希望读者能够更好地理解和应用算法与数据结构。