排序算法五——堆排序

来源:互联网 发布:ps3验证游戏数据 编辑:程序博客网 时间:2024/05/18 02:02

排序算法五:堆排序

其实堆排序本质上也是选择排序,只不过选择的方法不一样。直接选择排序法是将第一个数字与后面所有数字比较,然后找到最大(或最小)的值,然后swap交换,这样第一个数字就是最大(或最小)的数字了。然后再将第二个数与剩下的所有数字比较,找到第二大(或第二小)的数字,然后交换。就这样依次选择下去,就排好序了。
那么堆排序其实跟选择排序一样,每次把最大值(或最小值)找到,找的方式是通过构建“大顶堆”或“小顶堆”来实现的,堆的最上方(树的根)一定是树的最大值(或最小值),然后将树的根与最后一个数字swap调换,然后再将剩下的数字构造为大顶堆,构建完成后再将树的根与倒数第二个数字swap调换,然后再把剩下的数字构建大顶堆,然后再调换…… 最后数字就排好序了。
根排序是不稳定的排序,因为他数字跳来跳去,换来换去。跳跃式的比较跟交换。(我知道你不知道这句话什么意思)。

这是我自己画的图,有点丑:
这里写图片描述

这个图很明显能看出,我是从0开始的,不是从1开始。
树有一个性质,就是左子树的编号是双亲编号的两倍(2*n),当然我这里编号是从0开始的,左子树的编号是双亲编号的两倍再加1(2*n + 1).

算法大概就是是先初始化大顶堆,然后再调换根与最后一个数字,然后再调整大顶堆,再调换,在调整……
你们自己看代码吧。

堆排序代码:

/*****************************************************     File name:5heap_sort.c Author: Tang Zhiqian  Date:2017-08-08 16:36*****************************************************/#include <stdio.h>#define MAX 10typedef int ElementType;typedef ElementType ARR[MAX];ARR arr = {10,5,1,6,2,7,3,8,4,9};int len = sizeof(ARR)/sizeof(ElementType);void HeapSort(ARR arr);void swap(int arr[],int i,int j);void HeapAdjust(ARR arr,int s,int max);    //调整为大(小)顶堆void print(ARR arr);int main(){    printf("排序前:\n");    print(arr);    HeapSort(arr);    printf("堆排序后:\n");    print(arr);    return 0;}void HeapSort(ARR arr){    int i;    for (i = (len-1)/2; i > 0; i--)  //从最后一个非叶子节点开始 ★    {        HeapAdjust(arr,i,len-1);    }    for (i = len - 1; i > 0; i--)    {        swap(arr,0,i);      //跟最后一个调换        HeapAdjust(arr,0,i - 1);   //重新调整为大顶堆    }}void HeapAdjust(ARR arr,int s,int max){    int temp = arr[s];    //记录根的值    int i;    for (i = 2*s + 1; i <= max; i = 2*s + 1)    //从根节点的左孩子开始往下循环    {        if (arr[i + 1] > arr[i] && i < max)  //如果右孩子大于左孩子,i++,i变为右孩子下标        {            i++;        }        if (temp >= arr[i])    //如果根节点值是最大的,那就跳出循环        {            break;        }        arr[s] = arr[i];   //到这步说明根节点不是最大的,让根节点等于大的值        s = i;    //记录贡献出值的位置    }    arr[s] = temp;     //循环结束,把贡献出值的位置赋值temp}void swap(int arr[],int i,int j){    ElementType temp;    temp = arr[i];    arr[i] = arr[j];    arr[j] = temp;}void print(ARR arr){    int i;    for (i = 0; i < len; i++)    {        printf("%d ",arr[i]);    }    printf("\n");}

我觉得代码里面注释的还比较清楚,可能只有我自己能看懂((●’◡’●))

程序运行结果:

这里写图片描述

美滋滋!没毛病!

关于堆排序的时间复杂度,平均时间复杂度O(nlogn)。他也突破了O(n^2).空间上也只用到一个temp,美滋滋!

原创粉丝点击