堆排序
堆排序分为两步,建堆和调整堆,这两步可以由一个函数完成,但这个函数每次只能调整一条线(每层选择一次左右)使其符合堆的定义,因此建堆需要从最后一个非叶子节点自底向上调整堆,每次调整堆时需要对比两个孩子与父节点的大小,将最大的孩子与父节点交换(大顶堆),由于大顶堆的每个节点都大于左右子节点,因此就找出了最大元素,之后将最大元素与数组末尾元素交换即可得到最大值,之后再调整堆来获取第二大的元素。
Python代码如下:
def HeapAdjust(lst,parent,end):
child = 2 * parent + 1
while child < end:
if child + 1 < end and lst[child + 1] > lst[child]:
child += 1
if lst[parent] >= lst[child]:
break
lst[parent],lst[child] = lst[child],lst[parent]
parent = child
child = 2 * parent + 1
def HeapSort(lst):
for i in range(int(len(lst)/2) - 1,-1,-1):
HeapAdjust(lst,i,len(lst))
for i in range(len(lst) - 1):
lst[0],lst[len(lst)- 1 - i] = lst[len(lst) - 1 - i],lst[0]
HeapAdjust(lst,0,len(lst) - 1 - i)
nums = [5,3,9,7,4,7,1,5,10]
HeapSort(nums)
print(nums)
C++代码如下:
#include <iostream>
using namespace std;
void AdjustHeap(int a[], int parent, int end){
int child = 2 * parent + 1;
while(child < end){
if(child + 1 < end && a[child + 1] > a[child]){
child++;
}
if(a[parent] >= a[child]){
return;
}
int temp = a[parent];
a[parent] = a[child];
a[child] = temp;
parent = child;
child = 2 * parent + 1;
}
}
void HeapSort(int a[], int root, int end){
for(int i = end / 2 - 1; i >= 0; i--){
AdjustHeap(a, i, end);
}
for(int i = 0; i < end - 1; i++){
int temp = a[0];
a[0] = a[end - i - 1];
a[end - i - 1] = temp;
AdjustHeap(a, 0, end - i - 1);
}
}
int main(){
int nums[10] = {1,5,9,8,6,3,0,4,7,5};
HeapSort(nums, 0, 10);
for(int i = 0; i < 10; i++){
cout << nums[i];
}
return 0;
}
对代码的理解:
1.一个完全二叉树结点的左孩子在数组中的下标值为2 * parent + 1。
2.建堆过程是自底向上构建堆,从第一个有孩子的节点开始向上构建,第一个有孩子的节点的下标为int(len(lst) / 2) - 1
。调整堆时是从上到下调整一条线(每层选择一次左右结点),假如调整堆时右孩子与父节点进行了一次交换,则之后只需调整以右孩子为根的子树。
3.代码if child + 1 < end and lst[child + 1] > lst[child]
要先判断child + 1与end的关系,再判断两个孩子的大小,因为如果lst的长度为偶数,即最后一个叶子结点是左孩子时,先判断两个孩子的大小会发生数组越界。
堆排序构建大顶堆的过程时间复杂度为O(n),重建大顶堆的时间复杂度为O(nlogn),总的时间复杂度为O(nlogn)。空间复杂度为O(1)。
堆排序是不稳定的算法,当树的同一层有两个相同数字而其中下标较大的一个在调整堆时与父节点交换位置,即到了本层的上一层,会出现相对位置变化的情况。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)