“算法和数据结构理解”以及这些技能需要掌握的知识点。
算法和数据结构理解
# 算法和数据结构理解
## 算法理解
- 排序算法
- 冒泡排序
- 选择排序
- 插入排序
- 归并排序
- 快速排序
- 堆排序
- 计数排序
- 桶排序
- 基数排序
- 查找算法
- 顺序查找
- 二分查找
- 哈希查找
- 树形查找(如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) // 2
left_half = arr[:mid]
right_half = arr[mid:]
# 递归排序左半部分和右半部分
left_half = merge_sort(left_half)
right_half