选择排序(简单选择排序、堆排序)

简单选择排序(Selection Sort)

1. 算法思想

它通过多次遍历数组,每次从未排序部分中选择最小(或最大)的元素,将其放到已排序部分的末尾(或开头),直到整个数组有序。


2. 示例

原始数组 :[64, 25, 12, 22, 11]

  • 第1轮(从未排序的n个元素中查找) :
    • 找到最小值 11,与第1个元素 64 交换。
    • 结果:[11, 25, 12, 22, 64]
  • 第2轮(从未排序的n - 1个元素中查找) :
    • 找到最小值 12,与第2个元素 25 交换。
    • 结果:[11, 12, 25, 22, 64]
  • 第3轮 :
    • 找到最小值 22,与第3个元素 25 交换。
    • 结果:[11, 12, 22, 25, 64]
  • 第4轮 :
    • 剩余部分已排序,无需交换。

最终结果 :[11, 12, 22, 25, 64]


4. 时间复杂度
  • 最坏情况 :O(n²)(当数组完全逆序时)。
  • 最好情况 :O(n²)(即使数组已排序,仍需比较所有元素)。
  • 平均情况 :O(n²)。

5. 空间复杂度
  • 原地排序 :O(1),只需常数级别的额外空间。

6. 稳定性
  • 不稳定 :当存在相等元素时,可能改变它们的相对顺序。比如L={2,2,1},第一趟排序:L={1,2, 2},最终排序:L={1,2, 2};可以看到元素两个2的顺序发生了变化。

8. 代码实现
c 复制代码
void SelectSort(ElemType A[], int n) {
	for (int i = 0; i < n; i++) {
		int min = i;
		//找到未排序元素中的最小值
		for (int j = i + 1; j < n; j++) 
			if (A[j] < A[min]) min = i;
		
		//将最小值放入已排序序列的末尾
		if (min != i)
			swap(A[i], A[min]);
	}
	
}

堆排序(Heap Sort)

1.堆的概念

n个关键字序列L1...n称为堆,当且仅当满足:

  • L(i) >= L(2i) 且 L(i) >= L(2 i+1) 此时为大顶堆或
  • L(i) <= L(2i) 且 L(i) <= L(2 i+1) 此时为小顶堆

2.创建堆(以大顶堆为例)

建堆步骤:

  • 确定最后一个非叶结点的序号i = n/2
  • 判断是否符合大顶堆规则
  • 如果符合则对第i-1个结点从步骤二开始
  • 如果不符合规则,则与较大的叶子结点交换,然后对其子树从步骤二开始

3.堆排序代码实现

堆排序分为两个主要阶段:建堆 和排序。

  1. 建堆:

    • 将无序数组调整为大顶堆(或小顶堆)。
    • 从最后一个非叶子节点开始,向上调整堆结构,确保每个子树满足堆的性质。
  2. 排序:

    • 将堆顶元素(最大值)与堆的最后一个元素交换,将最大值"移出"堆。
    • 缩小堆的范围(排除已排序部分),对剩余部分重新调整为堆。
    • 重复上述过程,直到堆为空。
c 复制代码
void AdjustHeap(Element A[], int k, int len) {
	A[0] = A[k];
	for(int i = 2 * k; i <= len; i = i * 2){
		if (i < len && A[i] < A[i + 1])
			i++;
		if (A[0] >= A[i]) break;
		else {
			A[k] = A[i];
			k = i;
		}
	}
	A[k] = A[0];
}

void BuildHeap(Element A[], int len) {
	for (int i = len / 2; i >= 1; i--) {
		AdjustHeap(A, i, len);
	}
}

void HeapSort(Element A[], int len) {
	BuildHeap(A, len);
	for (int i = len; i > 1; i--) {
		Swap(A[i], A[1]);
		AdjustHeap(A, 1, i - 1);
	}
}

当从大量数据中选取前k大或前k小的元素时,堆排序可以表现出较优的时间复杂度。


4. 时间复杂度
  • 建堆 :O(n)
  • 排序 :每次调整堆的时间复杂度为 O(log n),需要调整 n-1 次。
  • 总时间复杂度 :O(n log n)

5. 空间复杂度
  • 原地排序 :O(1),只需常数级别的额外空间。

6. 稳定性
  • 不稳定:堆排序可能改变相等元素的相对顺序。可以以{1,2,2}将其调整为大顶堆为例。
相关推荐
Dumbness1 小时前
UIA 读微信群消息没有 id,怎么判断哪条是新的:后缀对齐在翻历史和撤回时整屏重报
python·算法
taka1 小时前
从 24x 到 141x:我用纯 Python 零依赖项目,扒开了 GPU 加速的性能黑洞
算法
UIU1141 小时前
P16237 [蓝桥杯 2026 省 B] 应急布线
数据结构·c++·算法·蓝桥杯
旖旎夜光1 小时前
LeetCode 315: 算右侧小于当前元素的个数(归并排序) —— 题解
c++·学习·算法·leetcode·排序算法
像风一样自由20202 小时前
2.如何用FastAPI把一个Python算法封装成HTTP服务
python·算法·fastapi
D e re k ZH2 小时前
保序回归:从 PAVA 到可并堆的单调约束优化
c++·算法·数据挖掘·回归·kotlin
青少儿编程课堂2 小时前
蓝桥杯·全国青少年信息素养大赛·电子学会Python/C++考级:字典树前缀树与单词检索统计
c++·python·算法·bfs·信息学竞赛
Nuanyt2 小时前
LeetCode Hot 100 链表专题2 3 题 (Java)
java·笔记·算法·leetcode·链表
海绵宝宝转agent2 小时前
LeetCodehot100题解
java·笔记·学习·算法·leetcode·深度优先
青少儿编程课堂3 小时前
2026蓝桥杯·全国青少年信息素养大赛·电子学会Python/C++考级:堆排序与优先队列解析
c++·python·算法·bfs·信息学竞赛