程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 算法珠玑--再看堆排序(Heap Sort)的實現

算法珠玑--再看堆排序(Heap Sort)的實現

編輯:C++入門知識

 


堆排序(Heap Sort)堆排序(HeapSort)是一樹形選擇排序。堆排序的特點是:在排序過程中,將R[l..n]看成是一棵完全二叉樹的順序存儲結構,利用完全二叉樹中雙親結點和孩子結點之間的內在關系,在當前無序區中選擇關鍵字最大(或最小)的記錄.

堆排序的最壞時間復雜度為O(nlogn)。堆序的平均性能較接近於最壞性能。
由於建初始堆所需的比較次數較多,所以堆排序不適宜於記錄數較少的文件。
堆排序是就地排序,輔助空間為O(1),
它是不穩定的排序方法。


如果需求是從很大的數據中選取特定的幾個最大活最小值,那麼堆排序是最好的選擇。

堆排序的基本步驟就是:

1.初始建堆

2.將堆頂元素與有序區的第一個元素交換

3.然後對堆頂元素開始調整堆,跳轉到2執行。直到全部有序。

 


聲明:下面算法的實現中,數組的存儲位於data[1]-------data[n]

該算法中最核心的算法是堆的調整算法:


[cpp]
//堆調整  
//data[],要排序的數組  
//target,要調整的元素位置  
//n,數組大小  
void AdjustHeap(int data[],int target,int n) 

    int nChild; 
    int nTemp; 
     
    nTemp = data[target];//暫存  
    while(target * 2 <= n) 
    { 
        nChild = target * 2;//nChild指向左孩子  
        if(nChild + 1 <= n && data[nChild] < data[nChild + 1]) 
        { 
            nChild++;//nChild指向關鍵字大的孩子(看是否有左孩子,若有,則左右孩子比較)  
        } 
        if(nTemp < data[nChild])//孩子節點比父節點大,則進行孩子節點移到父節點的位置  
        { 
            data[target] = data[nChild]; 
            target = nChild;//再處理剛剛調整過的節點的字節點  
        } 
        else break; 
    } 
    data[target] = nTemp;//最後將要調整的元素放到合適的位置  

//堆調整
//data[],要排序的數組
//target,要調整的元素位置
//n,數組大小
void AdjustHeap(int data[],int target,int n)
{
 int nChild;
 int nTemp;
 
 nTemp = data[target];//暫存
 while(target * 2 <= n)
 {
  nChild = target * 2;//nChild指向左孩子
  if(nChild + 1 <= n && data[nChild] < data[nChild + 1])
  {
   nChild++;//nChild指向關鍵字大的孩子(看是否有左孩子,若有,則左右孩子比較)
  }
  if(nTemp < data[nChild])//孩子節點比父節點大,則進行孩子節點移到父節點的位置
  {
   data[target] = data[nChild];
   target = nChild;//再處理剛剛調整過的節點的字節點
  }
  else break;
 }
 data[target] = nTemp;//最後將要調整的元素放到合適的位置
}
整體實現代碼:


[cpp]
****************
 * 堆排序算法
 * 排序數組下標從1開始
 */ 
#include <stdio.h>  
 
enum{MAX = 1000+1,}; 
     
int data[MAX]; 
static inline swap(int x,int y) 
{/*
    x ^= y;
    y ^= x;
    x ^= y;
    */ 
    int tmp; 
    tmp = data[x]; 
    data[x] = data[y]; 
    data[y] = tmp; 

//堆調整  
//data[],要排序的數組  
//target,要調整的元素位置  
//n,數組大小  
void AdjustHeap(int data[],int target,int n) 

    int nChild; 
    int nTemp; 
     
    nTemp = data[target];//暫存  
    while(target * 2 <= n) 
    { 
        nChild = target * 2; 
        if(nChild + 1 <= n && data[nChild] < data[nChild + 1]) 
        { 
            nChild++;//nChild指向關鍵字大的孩子  
        } 
        if(nTemp < data[nChild]) 
        { 
            data[target] = data[nChild]; 
            target = nChild;//再處理剛剛調整過的節點的字節點  
        } 
        else break; 
    } 
    data[target] = nTemp;//最後將要調整的元素放到合適的位置  

 
//堆排序算法  
//data,要排序的數組  
//n,數組大小  
void HeapSort(int data[],int n) 

    int i; 
    //初始建堆  
    for(i = n/2;i > 0;--i) 
    { 
        AdjustHeap(data,i,n); 
    } 
    //每次循環將堆頂元素與有序區第一個元素交換,然後再調整堆  
    for(i = n;i > 1;--i) 
    { 
        swap(1,i); 
        AdjustHeap(data,1,i - 1); 
    } 

 
int main() 

    freopen("random","r",stdin); 
    freopen("oder","w",stdout); 
    int i; 
    for(i = 1;i <= MAX;++i) 
    { 
        scanf("%d",&data[i]); 
    } 
    //stderr("開始排序\n");  
    HeapSort(data,MAX); 
    //stderr("排序結束\n");  
    for(i = 1;i <= MAX;++i) 
    { 
        printf("%d\n",data[i]); 
    } 
    return 0; 

/****************
 * 堆排序算法
 * 排序數組下標從1開始
 */
#include <stdio.h>

enum{MAX = 1000+1,};
 
int data[MAX];
static inline swap(int x,int y)
{/*
 x ^= y;
 y ^= x;
 x ^= y;
 */
 int tmp;
 tmp = data[x];
 data[x] = data[y];
 data[y] = tmp;
}
//堆調整
//data[],要排序的數組
//target,要調整的元素位置
//n,數組大小
void AdjustHeap(int data[],int target,int n)
{
 int nChild;
 int nTemp;
 
 nTemp = data[target];//暫存
 while(target * 2 <= n)
 {
  nChild = target * 2;
  if(nChild + 1 <= n && data[nChild] < data[nChild + 1])
  {
   nChild++;//nChild指向關鍵字大的孩子
  }
  if(nTemp < data[nChild])
  {
   data[target] = data[nChild];
   target = nChild;//再處理剛剛調整過的節點的字節點
  }
  else break;
 }
 data[target] = nTemp;//最後將要調整的元素放到合適的位置
}

//堆排序算法
//data,要排序的數組
//n,數組大小
void HeapSort(int data[],int n)
{
 int i;
 //初始建堆
 for(i = n/2;i > 0;--i)
 {
  AdjustHeap(data,i,n);
 }
 //每次循環將堆頂元素與有序區第一個元素交換,然後再調整堆
 for(i = n;i > 1;--i)
 {
  swap(1,i);
  AdjustHeap(data,1,i - 1);
 }
}

int main()
{
 freopen("random","r",stdin);
 freopen("oder","w",stdout);
 int i;
 for(i = 1;i <= MAX;++i)
 {
  scanf("%d",&data[i]);
 }
 //stderr("開始排序\n");
 HeapSort(data,MAX);
 //stderr("排序結束\n");
 for(i = 1;i <= MAX;++i)
 {
  printf("%d\n",data[i]);
 }
 return 0;
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved