堆排序
Posted happyknockoncode
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了堆排序相关的知识,希望对你有一定的参考价值。
堆排序
大根堆,小根堆:所有非叶子节点大于或者小于其孩子节点。
用大根堆进行从小到大的排序
建立大根堆:从下往上,从右往左遍历非叶子节点,判断其是否符合大根堆性质,若不符合,则交换节点位置,直至建出大根堆。
大根堆根节点一定是被排序的这段数值的最大值,交换堆尾堆首数值,堆尾指针前移(有没有冒泡的感觉?最大值逐渐飘到堆尾)
当前堆只有根节点不符合大根堆性质,所以从根节点开始,向下找到合适的位置即可
1#include<stdio.h>
2#include<iostream>
3using namespace std;
4
5/**刚还奇怪,为什么从小到大排序用的是大根堆?
6仔细看,建好堆以后,根节点是最大值,可是!!!
7交换了堆尾和堆首的值,那么最大值就跑到了后面.
8交换后,这个堆尾就算最大值了 ,不用管,再排序前面 n-1 个节点
9同理,每次最大值都跑到了后面
10*/
11
12
13/**以 k 为根的完全二叉树,分别以2*K 和 2*k+1 为根的左右子树为大根堆*/
14/**使 k 为根的树满足堆的性质*/
15void sift(int a[],int k,int m)
16{
17 int x=a[k];
18 int i=k;
19 int j=k*2;
20 bool finish=false;
21 while(j<=m&&!finish)
22 {
23 if(j+1<=m&&a[j]<a[j+1])
24 j=j+1;/**此时 j 指向最大子树根节点*/
25
26 if(x>=a[j])
27 finish=true;
28 else/**若是比子树根小,交换后还得考虑下层大小关系*/
29 {
30 a[i]=a[j];
31 i=j;
32 j=2*i;
33 }
34 }
35 a[i]=x;
36}
37void crateHeap(int a[],int n)
38{
39 /**从最后一个非叶子节点往上筛选建堆*/
40 for(int i=n/2;i>=1;i--)
41 sift(a,i,n);
42}
43void heapSort(int a[],int n)
44{
45 /**建大根堆后 ,保证了下面的数字不会大于上面的数字*/
46 crateHeap(a,n);
47 /**对 a 数组进行 从小到大 堆排序*/
48 for(int i=n;i>=2;i--)
49 {
50 /**每次得到的最大值跑到了后面*/
51 swap(a[i],a[1]);
52
53
54 /**交换以后只有堆顶元素是不合法的,所以下面只是为了
55 给堆顶元素找到一个合适的位置*/
56 /**对a[1~i-1]调整成堆*/
57 sift(a,1,i-1);
58 }
59}
60int main()
61{
62 int a[12]={0,88,32,34,12,34,66,52,33,25,20};
63 heapSort(a,10);
64 for(int i=1;i<=10;i++)
65 printf("%d ",a[i]);
66 return 0;
67}
以上是关于堆排序的主要内容,如果未能解决你的问题,请参考以下文章