zoukankan      html  css  js  c++  java
  • 数据结构:堆排序

    堆排序(Heap Sort)是指利用堆这种数据结构所设计的一种排序算法。
    因此,学习堆排序之前,有必要了解堆!

    我们知道,堆分为"最大堆"和"最小堆"。最大堆通常被用来进行"升序"排序,而最小堆通常被用来进行"降序"排序。
    鉴于最大堆和最小堆是对称关系,理解其中一种即可。本文将对最大堆实现的升序排序进行详细说明。

    最大堆进行升序排序的基本思想:
    ① 初始化堆:将数列a[1...n]构造成最大堆。
    ② 交换数据:将a[1]和a[n]交换,使a[n]是a[1...n]中的最大值;然后将a[1...n-1]重新调整为最大堆。 接着,将a[1]和a[n-1]交换,使a[n-1]是a[1...n-1]中的最大值;然后将a[1...n-2]重新调整为最大值。 依次类推,直到整个数列都是有序的。

    实现中用到了"数组实现的二叉堆的性质"。
    在第一个元素的索引为 0 的情形中:
    性质一:索引为i的左孩子的索引是 (2*i+1);
    性质二:索引为i的左孩子的索引是 (2*i+2);
    性质三:索引为i的父结点的索引是 floor((i-1)/2);

    堆排序实现代码(基于升序排列):

     1 //堆排序
     2 #include <iostream>
     3 #include <cstring>
     4 #include <string>
     5 #include <cmath>
     6 #include <algorithm>
     7 using namespace std;
     8 void heapSortDown(int a[],int start,int end)
     9 {
    10     int c=start;
    11     int l=c*2+1;
    12     int temp=a[c];
    13     for(;l<=end;c=l,l=l*2+1)
    14     {
    15         if(l<end&&a[l]<a[l+1]) l++;
    16         if(temp>=a[l]) break;
    17         else 
    18         {
    19             a[c]=a[l];
    20             a[l]=temp;
    21         }
    22     }
    23 }
    24 void heapsort_asc(int a[],int n)
    25 {
    26     int i,temp;
    27     for(i=n/2-1;i>=0;i--) heapSortDown(a,i,n-1);
    28     for(i=n-1;i>0;i--)
    29     {
    30         temp=a[0];
    31         a[0]=a[i];
    32         a[i]=temp;
    33         heapSortDown(a,0,i-1);
    34     }
    35 }
    36 int main()
    37 {
    38     int a[]={9999,4532,1234,9067,1345,6789,5432,6547,9801,100001};
    39     int ilen=sizeof(a)/sizeof(a[0]);
    40     cout<<"before sort:
    ";
    41     for(int i=0;i<ilen;i++) cout<<a[i]<<" ";
    42     cout<<endl;
    43     heapsort_asc(a,ilen); 
    44     cout<<"after sort:
    ";
    45     for(int i=0;i<ilen;i++) cout<<a[i]<<" ";
    46     cout<<endl;
    47  } 

    堆排序升序代码:

     1 /* 
     2  * (最大)堆的向下调整算法
     3  *
     4  * 注:数组实现的堆中,第N个节点的左孩子的索引值是(2N+1),右孩子的索引是(2N+2)。
     5  *     其中,N为数组下标索引值,如数组中第1个数对应的N为0。
     6  *
     7  * 参数说明:
     8  *     a -- 待排序的数组
     9  *     start -- 被下调节点的起始位置(一般为0,表示从第1个开始)
    10  *     end   -- 截至范围(一般为数组中最后一个元素的索引)
    11  */
    12 void maxheap_down(int a[], int start, int end)
    13 {
    14     int c = start;            // 当前(current)节点的位置
    15     int l = 2*c + 1;        // 左(left)孩子的位置
    16     int tmp = a[c];            // 当前(current)节点的大小
    17     for (; l <= end; c=l,l=2*l+1)
    18     {
    19         // "l"是左孩子,"l+1"是右孩子
    20         if ( l < end && a[l] < a[l+1])
    21             l++;        // 左右两孩子中选择较大者,即m_heap[l+1]
    22         if (tmp >= a[l])
    23             break;        // 调整结束
    24         else            // 交换值
    25         {
    26             a[c] = a[l];
    27             a[l]= tmp;
    28         }
    29     }
    30 }
    31 
    32 /*
    33  * 堆排序(从小到大)
    34  *
    35  * 参数说明:
    36  *     a -- 待排序的数组
    37  *     n -- 数组的长度
    38  */
    39 void heap_sort_asc(int a[], int n)
    40 {
    41     int i;
    42 
    43     // 从(n/2-1) --> 0逐次遍历。遍历之后,得到的数组实际上是一个(最大)二叉堆。
    44     for (i = n / 2 - 1; i >= 0; i--)
    45         maxheap_down(a, i, n-1);
    46 
    47     // 从最后一个元素开始对序列进行调整,不断的缩小调整的范围直到第一个元素
    48     for (i = n - 1; i > 0; i--)
    49     {
    50         // 交换a[0]和a[i]。交换后,a[i]是a[0...i]中最大的。
    51         swap(a[0], a[i]);
    52         // 调整a[0...i-1],使得a[0...i-1]仍然是一个最大堆。
    53         // 即,保证a[i-1]是a[0...i-1]中的最大值。
    54         maxheap_down(a, 0, i-1);
    55     }
    56 }

    参考:https://www.cnblogs.com/skywang12345/p/3602162.html(包含升序,降序)

    天晴了,起飞吧
  • 相关阅读:
    05用户故事与敏捷方法笔记之五
    04用户故事与敏捷方法笔记之四
    03用户故事与敏捷方法笔记之三
    框架学习.关于内省api操作bean属性
    02用户故事与敏捷方法笔记之二
    01用户故事与敏捷方法笔记之一
    问题账户需求分析
    2017年秋季个人阅读计划
    第二冲刺项目进展
    典型用户与场景
  • 原文地址:https://www.cnblogs.com/jianqiao123/p/12150511.html
Copyright © 2011-2022 走看看