zoukankan      html  css  js  c++  java
  • 选择排序------堆排序

    堆排序快速排序归并排序一样都是时间复杂度为O(N*logN)的几种常见排序方法。

    堆排序有点类似选择排序,都是每次选出最大的数或最小的数。

    对于堆,由于其根节点为堆中最大的节点,因此每次只需取出其根节点,然后重新建堆,再重复前面操作

    故按如下步骤:

      首先可以看到堆建好之后堆中第0个数据是堆中最大的数据。取出这个数据再执行下堆的删除操作。这样堆中第0个数据又是堆中最大的数据,重复上述步骤直至堆中只有一个数据时就直接取出这个数据。

      由于堆也是用数组模拟的,故堆化数组后,第一次将A[0]与A[n - 1]交换,再对A[0…n-2]重新恢复堆。第二次将A[0]与A[n – 2]交换,再对A[0…n - 3]重新恢复堆,重复这样的操作直到A[0]与A[1]交换。由于每次都是将最小的数据并入到后面的有序区间,故操作完成后整个数组就有序了。

         在前面介绍了对的删除,插入和建堆等操作(加了哨兵,数组从第1个元素开始),下面实现堆排序。

    #include <iostream>
    
    using namespace std;
    
    struct  Heap_Struct{
         int *Element;
         int size;
         int capacity;
    };
    
    void Heap_Sort(void); 
    Heap_Struct*  Heap_Construct(int *arr,int len);
    int Heap_Delete(Heap_Struct *h);
    
    int main()
    {
        Heap_Sort( );
        return 0;
    }
    
    Heap_Struct*  Heap_Construct(int *arr,int len)
    {/*根据长度为len的数组创建最大堆*/
        
          Heap_Struct  *H_tmp= new Heap_Struct;
          H_tmp->Element=new int[len+1];
          H_tmp->size=len;
          H_tmp->capacity=len;
    
          int i,start,tmp=0;
          int parent,child;
          for (i=1;i<len+1;i++)
            {
                H_tmp->Element[i]=arr[i-1];
                if(tmp<arr[i])
                    tmp=arr[i];
            }
          H_tmp->Element[0]=tmp+5;  
          start=i/2;
          for(i=start;i>0;i--)
          {
               parent=i;
                while(2*parent<=H_tmp->size)  //存在子节点 
             {
                if(2*parent+1<=len && H_tmp->Element[2*parent+1]>H_tmp->Element[2*parent] && H_tmp->Element[2*parent+1]>H_tmp->Element[parent])
                {
                       tmp=H_tmp->Element[parent];
                       H_tmp->Element[parent]=H_tmp->Element[2*parent+1];
                       H_tmp->Element[2*parent+1]=tmp;      
                       parent=2*parent+1;
                }
               else if(H_tmp->Element[2*parent]>H_tmp->Element[parent])
                {
                        tmp=H_tmp->Element[parent];
                        H_tmp->Element[parent]=H_tmp->Element[2*parent];
                        H_tmp->Element[2*parent]=tmp; 
                        parent=2*parent;      
                }
               else 
                   break;
             }
          }
           return H_tmp;
    }        
    
    int Heap_Delete(Heap_Struct *h)
    {
         int MaxData=h->Element[1];
         int tmp=h->Element[h->size--];/*取出最后一个元素并将堆的长度减1*/
         int i=1;
         while(2*i<=h->size && h->Element[2*i]>tmp)
         {
                if((2*i+1)<=h->size && h->Element[2*i+1]>h->Element[2*i] && h->Element[2*i+1]>tmp)  /*右节点存在且大于左节点且大于插入的值,则将右节点移到其父节点并继续向上过滤*/
               { 
                        h->Element[i]=h->Element[2*i+1];;
                        i=2*i+1;
               }
                else if(h->Element[2*i]>tmp)   /*左节点大且大于插入的值,则将左节点移到其父节点并继续向上过滤*/
               {
                       h->Element[i]=h->Element[2*i];
                       i=2*i;
                }
                else
                       break;
         }
    
            h->Element[i]=tmp;   /*将最后一个数插到堆中*/
          return MaxData;
    }                      
    
    void Heap_Sort(void)
    {
        int arr[]={79,66,43,83,30,87,38,55,91,72,49,9};
        int len=12;
        cout <<"原始数据:"; 
        for(int i=0;i<len;i++)
            cout << arr[i] <<' ';
        cout << endl;
        
        Heap_Struct* h=Heap_Construct(arr,len); //建堆
        
        cout <<"堆中数据:";
        for(int i=1;i<len+1;i++)
            cout << h->Element[i] << ' ';
        cout <<endl;
        
        for(int i=0;i<len;i++)                 //循环删除堆的根节点,并将其插入到数组的末尾 
            arr[len-i-1]=Heap_Delete(h);
        
        cout <<"排序后数据:" ;
        for(int i=0;i<12;i++)
            cout << arr[i] <<' ';
        cout <<endl;
    }

    结果为:

      

      由于每次重新恢复堆的时间复杂度为O(logN),共N - 1次重新恢复堆操作,再加上前面建立堆时N / 2次向下调整,每次调整时间复杂度也为O(logN)。二次操作时间相加还是O(N * logN)。故堆排序的时间复杂度为O(N * logN)。STL也实现了堆的相关函数,可以参阅《STL系列之四 heap 堆》。

  • 相关阅读:
    10分钟教你用Python玩转微信之抓取好友个性签名制作词云
    1. 配置win7下odbc数据源找不到数据库驱动的问题
    1. 加签和会签的区别
    4. mysql 1449 : The user specified as a definer ('test'@'%') does not exist 解决方法
    1. 在config.ini文件中加入dm.park.time=1,会使uap中的tomcat启动加快
    37. sqlplus工具连接服务端或其他电脑的oracle方式
    36. Oracle查询数据库中所有表的记录数
    4. mysql 查看数据库中所有表的记录数
    35. Oracle监听器启动出错:本地计算机上的OracleOraDb11g_home1TNSListener服务启动后又停止了解决方案
    4. powerdesigner 生成sql脚本步骤
  • 原文地址:https://www.cnblogs.com/wujing-hubei/p/6072036.html
Copyright © 2011-2022 走看看