目录
- 算法和数据结构理解
- 概念及实际列子
- 一、排序算法
- 概念
- 冒泡排序 (Bubble Sort)
- 选择排序 (Selection Sort)
- 插入排序 (Insertion Sort)
- 归并排序 (Merge Sort)
- 快速排序 (Quick Sort)
- 堆排序 (Heap Sort)
- 计数排序 (Counting Sort)
- 桶排序 (Bucket Sort)
- 基数排序 (Radix Sort)
- 二、查找算法概念及代码示例
- 1. 顺序查找(Linear Search)
- 2. 二分查找(Binary Search)
- 3. 哈希查找(Hash Search)
- 4. 树形查找(如AVL树、红黑树)
- AVL树代码示例
- 三、图算法
- 图算法概念
- 深度优先搜索(DFS)
- 广度优先搜索(BFS)
- 最短路径算法
- 最小生成树算法
“算法和数据结构理解”以及这些技能需要掌握的知识点。
算法和数据结构理解
# 算法和数据结构理解## 算法理解
- 排序算法- 冒泡排序- 选择排序- 插入排序- 归并排序- 快速排序- 堆排序- 计数排序- 桶排序- 基数排序
- 查找算法- 顺序查找- 二分查找- 哈希查找- 树形查找(如AVL树、红黑树)
- 图算法- 深度优先搜索- 广度优先搜索- 最短路径算法(如Dijkstra、Floyd-Warshall)- 最小生成树算法(如Prim、Kruskal)## 数据结构理解
- 线性数据结构- 数组- 链表(单向链表、双向链表、循环链表)- 栈- 队列
- 树形数据结构- 二叉树- AVL树- 红黑树- B树- B+树- 堆(二叉堆、斐波那契堆)
- 图形数据结构- 邻接矩阵- 邻接表## 性能测试与评估
- 时间复杂度分析
- 空间复杂度分析
- 稳定性测试
- 边界条件测试## 设计测试场景与用例
- 根据算法特性设计测试场景
- 构造有效与无效的测试用例
- 验证算法的正确性与效率
概念及实际列子
一、排序算法
概念
冒泡排序(Bubble Sort):
冒泡排序是一种简单的交换排序算法。它重复地遍历要排序的元素,比较每对相邻的元素,如果它们的顺序错误就交换它们。
时间复杂度:最好情况下为O(n),最坏情况下为O(n^2)。
选择排序(Selection Sort):
选择排序是一种简单直观的排序算法。它的工作原理是每次从未排序的元素中选择最小(或最大)的元素,放到已排序的序列末尾。
时间复杂度:始终为O(n^2),无论输入数据的排列情况如何。
插入排序(Insertion Sort):
插入排序是一种简单直观的排序算法。它的工作原理是构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
时间复杂度:最好情况下为O(n),最坏情况下为O(n^2)。
快速排序(Quick Sort):
快速排序是一种分治算法。它通过选择一个基准元素,将原始序列分割成两个子序列,然后对子序列进行递归排序来实现排序。
时间复杂度:最好情况下为O(nlogn),最坏情况下为O(n^2),平均情况下为O(nlogn)。
归并排序(Merge Sort):
归并排序是一种分治算法。它将原始序列递归地分成较小的序列,直到每个子序列只有一个元素,然后将相邻的子序列两两合并,最终得到排序后的序列。
时间复杂度:始终为O(nlogn)。
堆排序(Heap Sort):
堆排序是一种选择排序算法。它利用了堆这种数据结构的性质,通过建立最大堆(或最小堆)来实现排序。
时间复杂度:始终为O(nlogn)。
以下分别是各种排序算法的Python代码示例:
冒泡排序 (Bubble Sort)
def bubble_sort(arr): n = len(arr) # 遍历所有数组元素 for i in range(n): # Last i elements are already in place for j in range(0, n - i - 1): # 遍历数组从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 ("排序后的数组:")
for i in range(len(arr)): print ("%d" %arr[i]),
在上面的代码中,我们定义了一个 bubble_sort 函数,它接受一个列表 arr 作为参数,并对其进行排序。
外层循环 for i in range(n) 遍历整个数组,由于每一轮冒泡排序后,最大的元素都会移到正确的位置(数组的末尾),所以下一轮就不需要再比较已经排好的元素。
内层循环 for j in range(0, n - i - 1) 用来在每一轮中比较相邻的元素,并交换位置(如果前一个元素比后一个元素大)。这样,每一轮结束后,都会有一个元素被放到正确的位置。
最终,数组 arr 就会被排序好,并通过 for 循环输出排序后的结果。
选择排序 (Selection Sort)
def selection_sort(arr): # 遍历所有数组元素 for i in range(len(arr)): # 找到当前未排序部分中的最小元素 min_idx = i for j in range(i+1, len(arr)): if arr[j] < arr[min_idx]: min_idx = j # 将找到的最小元素交换到已排序序列的末尾 arr[i], arr[min_idx] = arr[min_idx], arr[i] # 测试数组
arr = [64, 34, 25, 12, 22, 11, 90] # 调用选择排序函数
selection_sort(arr) # 输出排序后的数组
print("排序后的数组:")
for i in range(len(arr)): print("%d" % arr[i]),
在这个代码中,我们首先获取数组的长度,然后开始遍历数组。对于每个位置 i,我们假设该位置上的元素是最小的,然后遍历从 i+1 到数组末尾的所有元素,如果发现一个更小的元素,我们就更新最小元素的索引。最后,我们将位置 i 上的元素与找到的最小元素进行交换。
通过这种方式,每次循环后,位置 i 上的元素都会是未排序部分中的最小元素,并且已经位于正确的位置上。最终,整个数组都会被排序。
选择排序的时间复杂度为 O(n^2),其中 n 是数组的长度。与冒泡排序相似,选择排序也不是最高效的排序算法,但对于小数据集或特定应用场景,它仍然是一个简单且可行的选择。
如果以上代码要选出最大的一个元素,我们只需要在内部循环中比较时改变比较的方向。即,我们需要将比较 arr[j] < arr[min_idx] 改为 arr[j] > arr[max_idx],并相应地更新变量名从 min_idx 到 max_idx
插入排序 (Insertion Sort)
def insertion_sort(arr): # 遍历从1到数组长度的所有元素 for i in range(1, len(arr)): # 当前需要排序的元素 key = arr[i] # 与已排序的元素从后往前逐个比较 j = i - 1 while j >= 0 and key < arr[j]: # 如果当前元素(已排序)大于key,将该元素移到下一位置 arr[j + 1] = arr[j] j -= 1 # 找到key的正确位置并插入 arr[j + 1] = key # 测试数组
arr = [12, 11, 13, 5, 6] # 调用插入排序函数
insertion_sort(arr) # 输出排序后的数组
print("排序后的数组:")
for i in range(len(arr)): print("%d" % arr[i]),
在这个代码中,我们首先从数组的第二个元素开始遍历(索引为1,因为索引0的元素默认已经是排序好的)。对于每个元素,我们将其存储在变量key中,并与它前面的已排序元素进行比较。如果前面的元素比key大,我们就将该元素向后移动一位。这个过程一直持续到找到key的正确位置,然后将key插入到该位置。
插入排序的时间复杂度在最坏情况下是O(n^2),其中n是数组的长度。尽管它的时间复杂度与冒泡排序和选择排序相同,但由于插入排序在实际应用中移动数据的操作较少,因此在某些情况下它比冒泡排序和选择排序更快。然而,对于大规模数据集,插入排序通常不是最高效的选择。
归并排序 (Merge Sort)
归并排序(Merge Sort)是一种分治策略的排序算法。它将一个大数组分割成两个小数组,分别对这两个小数组进行排序,然后将已排序的小数组合并成一个大的有序数组。以下是归并排序的Python代码示例:
def merge_sort(arr):# 递归终止条件:如果数组长度为0或1,则直接返回if len(arr) <= 1:return arr# 分割数组mid = len(arr) // 2left_half = arr[:mid]right_half = arr[mid:]# 递归排序左半部分和右半部分left_half = merge_sort(left_half)right_half