堆排序

2021-02-17 18:17

阅读:496

标签:--   class   方法   nlogn   替换   递归   flag   时间   稳定性   

概念

分为大顶堆和小顶堆,是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。堆排序可以用到上一次的排序结果,所以不像其他一般的排序方法一样,每次都要进行n-1次的比较,复杂度为O(nlogn)。

 

完全二叉树的性质

 

将堆的内容填入一个一维数组,这样通过下标就能计算出每个结点的父子节点,编号顺序从0开始,从左往右,从上至下层次遍历。a[10] = {2,8,5,10,9,12,7,14,15,13}

 

若一个结点的下标为k,那么它的父结点为(k-1)/2,其子节点为2k+1和2k+2

 

例:数字为10的节点的下标为3,父结点为1号:8,子节点为7号和8号:14,15

 

流程

 

1)利用给定数组创建一个堆H[0..n-1],输出堆顶元素

 

2)以最后一个元素代替堆顶,调整成堆,输出堆顶元素

 

3)把堆的尺寸缩小1

 

4) 重复步骤2,直到堆的尺寸为1

先构造一个大顶堆,移除最大元素(根节点),将最大元素与最小元素替换,重新构造一个大顶堆,循环移除

实现代码

 

 1 void HeapBuild(vectorint> &nums, int root, int length)
 2 {
 3     int lchild = root * 2 + 1;
 4     if (lchild //左子结点下标不能超出数组的长度
 5     {
 6         int flag = lchild;//flag保存左右节点中最大值的下标
 7         int rchild = lchild + 1;
 8         if (rchild  nums[flag])
 9             flag = rchild;//找出左右子结点中的最大值
10 
11         if (nums[root]  nums[flag])
12         {
13             swap(nums[root], nums[flag]);
14             HeapBuild(nums, flag, length);//从此次最大子节点的那个位置开始递归建堆
15         }
16     }
17 }
18 
19 void HeapSort(vectorint> &nums)
20 {
21     int len = nums.size();
22     for (int i = len / 2; i >= 0; i--)//从最后一个非叶子节点的父节点开始建堆
23     {
24         HeapBuild(nums, i, len);
25     }
26 
27     for (int j = len - 1; j > 0; j--)
28     {
29         swap(nums[0], nums[j]);//交换首尾元素,将最大值交换到数组的最后位置保存
30         HeapBuild(nums, 0, j);//去除最后位置的元素重新建堆,此处j表示数组的长度,最后一个位置下标变为len-2
31     }
32 }

 

 

性能

最差时间复杂度O(n log n)
最优时间复杂度O(n log n)
平均时间复杂度O(n log n)
最差空间复杂度O(n)

稳定性:不稳定

 

 

注意:此排序方法不适用于个数少的序列,因为初始构建堆需要时间

 

堆排序

标签:--   class   方法   nlogn   替换   递归   flag   时间   稳定性   

原文地址:https://www.cnblogs.com/jpzhu/p/12696863.html

上一篇:直接插入排序

下一篇:Python 练习实例62


评论


亲,登录后才可以留言!