zoukankan      html  css  js  c++  java
  • 堆排序

    堆排序:

    要知道堆排序,首先要了解一下二叉树的模型。

    下图就是一颗二叉树,具体的情况我后续会分享的。

    那么堆排序中有两种情况(看上图理解):

        大根堆:  就是说父节点要比左右孩子都要大。

        小根堆:  就是说父节点要比左右孩子都要小。

    那么要实现堆排序,必须要做两件事情:

       第一:构建大根堆。

               首先上图:

               

    首先这是一个无序的堆,那么我们怎样才能构建大根堆呢?

         第一步: 首先我们发现,这个堆中有2个父节点(2,,3);

         第二步: 比较2这个父节点的两个孩子(4,5),发现5大。

         第三步: 然后将较大的右孩子(5)跟父节点(2)进行交换,至此3的左孩子堆构建完毕,

                     如图:

                             

         第四步: 比较第二个父节点(3)下面的左右孩子(5,1),发现左孩子5大。

         第五步: 然后父节点(3)与左孩子(5)进行交换,注意,交换后,堆可能会遭到破坏,

                     必须按照以上的步骤一,步骤二,步骤三进行重新构造堆。

               

    最后构造的堆如下:

                     

       第二:输出大根堆。

                 至此,我们把大根堆构造出来了,那怎么输出呢?我们做大根堆的目的就是要找出最大值,

             那么我们将堆顶(5)与堆尾(2)进行交换,然后将(5)剔除根堆,由于堆顶现在是(2),

             所以破坏了根堆,必须重新构造,构造完之后又会出现最大值,再次交换和剔除,最后也就是我们

             要的效果了。

    堆的定义:n个关键字序列Kl,K2,…,Kn称为(Heap),当且仅当该序列满足如下性质(简称为堆性质):

    ki<=k(2i)且ki<=k(2i+1)(1≤i≤ n/2),当然,这是小根堆,大根堆则换成>=号。//k(i)相当于二叉树的非叶子结点,K(2i)则是左子节点,k(2i+1)是右子节点
     
          堆排序利用了大根堆(或小根堆)堆顶记录的关键字最大(或最小)这一特征,使得在当前无序区中选取最大(或最小)关键字的记录变得简单。

    说明:它是不稳定的排序方法。(排序的稳定性是指如果在排序的序列中,存在前后相同的两个元素的话,排序前 和排序后他们的相对位置不发生变化)

     1 #include<iostream>
     2 #include <ctime>  //使用了time() 函数 
     3 #include <cstdlib>    //使用了srand()函数 
     4 
     5 const int N=3005;
     6 int a[N];
     7 using namespace std;
     8 //堆排序
     9 //整理节点time:O(lgn)
    10 
    11 void AdjustHeap(int *a,int parent,int length)
    12 {
    13      //temp保存当前父节点 
    14     int temp=a[parent];
    15     //得到左孩子(这可是二叉树的定义,大家看图也可知道)
    16     int child=2*parent;
    17     while(child<=length)
    18     {
    19         //如果parent有右孩子,则要判断左孩子是否小于右孩子
    20         if (child + 1 < length && a[child] < a[child + 1])   child++;//此方法用了点小技巧,大家认真思考一下 
    21         if(temp>=a[child])  break;    //父节点大于子节点,就不用了,建堆完成 
    22         //另一种情况则是小于
    23         a[parent]=a[child];  //大的子节点赋值给父节点 
    24         parent=child;     //子节点做为父节点 
    25         child=2*parent;   //步长增,进入下一节点 
    26     }
    27     a[parent]=temp;   //完成后,将temp赋值给此节点即可完成建堆 
    28 }
    29 
    30 //堆排序time:O(nlgn)
    31 void HeapSort(int*a,int n)
    32 {
    33   int i;
    34   for(i=n/2;i>=1;i--)     //从最后一个父节点一至到第一个 
    35   {
    36     AdjustHeap(a,i,n);     //对每个父节点进行一次建堆 
    37   }
    38   //最后输出堆元素
    39  for(int i=n;i>1;i--)
    40  {
    41      //堆顶与当前的第i个元素进行对调
    42      int temp=a[1];
    43      a[1]=a[i];
    44      a[i]=temp;
    45      //对调后,再对1...i-1的元素进行建堆,此时只需要从第1个元素开始到最底层即可
    46       AdjustHeap(a,1,i-1); 
    47  }
    48 }
    49 
    50 int main()
    51 {
    52     //随机产生3000个数存入数组a中 
    53     srand(int(time(0)));      //利用时间函数time(),产生每次不同的随机数种子
    54     for(int i=1;i<=3000;i++) a[i]=rand();  //随机产生3000个数存于数组a中 (从1开始) 
    55     clock_t start = clock();     // 计时开始
    56     HeapSort(a, 3000);                   //对数组a进行排序(从1开始) 
    57     clock_t end = clock();       //计时结束
    58     for(int i=1;i<=20;i++) cout<<a[i]<<' ';    //输出前20个数据(已从小到大排序) 
    59     cout<<endl<<"堆排排序耗时为:"<<end-start<<"ms"<<endl;     //输出排序所用的时间:结束时间-开始时间(单位为毫秒)
    60     return 0;
    61 }
  • 相关阅读:
    学用Fireworks中的特效1 建站之家
    网页页面尺寸一般设置多大才合适
    什么是哲学为基础的设计模式?
    10个步骤让你成为高效的Web开发者
    到移动开发大会 听《植物大战僵尸》成功秘诀
    [转]设置IE背景色保护你的眼睛视力_鹤壁吧_贴吧
    乔布斯在斯坦福大学演讲时说
    XQ4 logo1.html
    你是一位领导者吗?企业领导者必须具备的10种才能
    对不起,我已爱上你
  • 原文地址:https://www.cnblogs.com/jjzzx/p/5072111.html
Copyright © 2011-2022 走看看