內部排序之堆排序的實現
堆排序(Heap Sort)只需要一個記錄大小的輔助空間,每個待排序的記錄僅佔有一個存儲空間。下面小編爲大家整理了內部排序之堆排序的實現,希望能幫到大家!
(1)基本概念
a)堆:設有n個元素的序列:
{k1, k2, ..., kn}
對所有的i=1,2,...,(int)(n/2),當滿足下面關係:
ki≤k2i,ki≤k2i+1
或 ki≥k2i,ki≥k2i+1
這樣的序列稱爲堆。
堆的兩種類型:
根結點最小的堆----小根堆。
根結點最大的堆----大根堆。
根結點稱爲堆頂,即:在一棵完全二叉樹中,所有非葉結點的'值均小於(或均大於)左、右孩子的值。
b)堆排序:是一種樹型選擇排序,特點是,在排序過程中,把R[1..n]看成是一個完全二叉樹的存儲結構,利用完全二叉樹雙親結點和孩子結點的內在關係,在當前無序區中選擇關鍵字最大(最小)的記錄。
(2)堆排序步驟:
1、從k-1層的最右非葉結點開始,使關鍵字值大(或小)的記錄逐步向二叉樹的上層移動,最大(或小)關鍵字記錄成爲樹的根結點,使其成爲堆。
2、逐步輸出根結點,令r[1]=r[i](i=n,,n-1,...,2),在將剩餘結點調整成堆。直到輸出所有結點。我們稱這個自堆頂到葉子的調整過程爲“篩選”。
(3)要解決的兩個問題:
1、如何由一個無序序列建成一個堆;
2、輸出一個根結點後,如何將剩餘元素調整成一個堆。
將一個無序序列建成一個堆是一個反覆“篩選”的過程。若將此序列看成是一個完全二叉樹,則最後一個非終端結點是第floor(n/2)個元素,由此“篩選”只需從第floor(n/2)個元素開始。
堆排序中需一個記錄大小的輔助空間,每個待排的記錄僅佔有一個存儲空間。堆排序方法當記錄較少時,不值得提倡。當n很大時,效率很高。堆排序是不穩定的。
堆排序的算法和篩選的算法如第二節所示。爲使排序結果是非遞減有序排列,我們在排序算法中先建一個“大頂堆”,即先選得一個關鍵字爲最大的記錄並與序列中最後一個記錄交換,然後對序列中前n-1個記錄進行篩選,重新將它調整爲一個“大頂堆”,然後將選得的一個關鍵字爲最大的記錄(也就是第一個元素)與當前最後一個記錄交換(全局看是第n-1個),如此往復,直到排序結束。由到,篩選應按關鍵字較大的孩子結點向下進行。
堆排序的算法描述如下:
複製代碼 代碼如下:
#include "iostream"
using namespace std;
#define MAXSIZE 20
typedef struct
{
int key;
//其他數據信息
}RedType;
typedef struct
{
RedType r[MAXSIZE+1];
int length;
}Sqlist;
typedef Sqlist HeapType; //堆採用順序表存儲表示
void HeapAdjust(HeapType &H,int s,int m) //已知H.r[s...m]中記錄的關鍵字出H.r[s]之外均滿足堆的定義,本函數調整H.r[s]的關鍵字,使H.r[s...m]成爲一個大頂堆(對其中記錄的關鍵字而言)
{
int j;
RedType rc;
rc=H.r[s];
for(j=2*s;j<=m;j*=2) //沿key較大的孩子結點向下篩選
{
if(j<m && (H.r[j]<H.r[j+1])) //j爲key較大的記錄的下標
++j;
if(>=H.r[j]) //rc應插入在位置s上
break;
H.r[s]=H.r[j]; //將左、右孩子較大的結點與父節點進行交換,建成大頂堆
s=j;
}
H.r[s]=rc; //插入
}
void HeapSort(HeapType &H) //對順序表H進行堆排序
{
int i;
for(i=th/2;i>0;--i) //由一個無序序列建成一個大頂堆,將序列看成是一個完全二叉樹,則最後一個非終端節點是第n/2個元素
HeapAdjust(H,i,th);
for(i=th;i>1;--i)
{
H.r[0]=H.r[1]; //將堆頂記錄和當前未經排序的子序列H.r[1...i]中最後一個記錄相互交換
H.r[1]=H.r[i];
H.r[i]=H.r[0];
HeapAdjust(H,1,i-1); //將H.r[1...i-1]重新調整爲大頂堆
}
}//HeapSort
void InputL(Sqlist &L)
{
int i;
printf("Please input the length:");
scanf("%d",&th);
printf("Please input the data needed to sort:n");
for(i=1;i<=th;i++) //從數組的第1個下標開始存儲,第0個下標作爲一個用於交換的臨時變量
scanf("%d",&L.r[i]);
}
void OutputL(Sqlist &L)
{
int i;
printf("The data after sorting is:n");
for(i=1;i<=th;i++)
printf("%d ",L.r[i]);
printf("n");
}
int main(void)
{
Sqlist H;
InputL(H);
HeapSort(H);
OutputL(H);
system("pause");
return 0;
}
不使用上面的結構體的另外一種方法如下:
複製代碼 代碼如下:
/*
*堆排序
*/
#include "iostream"
using namespace std;
#define N 10
int array[N];
void man_input(int *array)
{
int i;
for(i=1;i<=N;i++)
{
printf("array[%d]=",i);
scanf("%d",&array[i]);
}
}
void mySwap(int *a,int *b)//交換
{
int temp;
temp=*a;
*a=*b;
*b=temp;
}
void heap_adjust(int *heap,int root,int len) //對堆進行調整,使下標從root到len的無序序列成爲一個大頂堆
{
int i=2*root;
int t=heap[root];
while(i<=len)
{
if(i<len)
{
if(heap[i]<heap[i+1])
i++;
}
if(t>=heap[i])
break;
heap[i/2]=heap[i];
i=2*i;
}
heap[i/2]=t;
}
void heapSort(int *heap,int len) //堆排序
{
int i;
for(i=len/2;i>0;i--) //由一個無序序列建成一個大頂堆,將序列看成是一個完全二叉樹,則最後一個非終端節點是第len/2個元素
{
heap_adjust(heap,i,len);
}
for(i=len;i>=1;i--)
{
mySwap(heap+i,heap+1); //將堆頂記錄與最後一個記錄相互交換
heap_adjust(heap,1,i-1); //將下標爲1~i-1的記錄重新調整爲大頂堆
}
}
void print_array(int *array,int n)
{
int k;
for(k=1;k<n+1;k++)
{
printf("%dt",array[k]);
}
}
int main(void)
{
man_input(array);
heapSort(array,N);
printf("nAfter sorted by the heap_sort algorithm:n");
print_array(array,N); //打印堆排序結果
system("pause");
return 0;
}
相關文章
-
C#排序算法之堆排序
關於C#排序算法的堆排序具體是怎麼樣的呢?下面小編爲大家整理了C#排序算法之堆排序,希望能幫到大家! 一、基本概念堆:這裏是指一種數據結構,而不是我們在C#中提到的用於存儲引用類型對象的地方。它可以被當成一棵完全二叉 -
排序之一:直接插入排序(C語言實現)
有很多時尚的女生都喜歡選擇一些好看的髮型,現在我們就一起來欣賞一下這些各種長度的女生的蛋卷頭髮型吧,這些 最新韓式蛋卷頭的燙捲髮型是特別的有氣質的,一起來欣賞一下這些顯氣質的髮型吧。無劉海的一款短髮的韓式風 -
堆排序算法及用C++實現基於最大堆的堆
還不知道堆排序算法是怎麼計算的嗎?下面小編爲大家整理了堆排序算法及用C++實現基於最大堆的堆,希望能幫到大家! 1、堆排序定義n個關鍵字序列Kl,K2,…,Kn稱爲堆,當且僅當該序列滿足如下性質(簡稱爲堆性質):(1) ki≤K2i且ki -
c語言中冒泡排序、插入排序、選擇排序算法比較
掌握好常用的排序算法,在實際的項目開發中可以節省很多的時間。每一種排序算法在執行的效率上是存在差別的,這些微小的時間差,也許在平常的聯繫當中感覺不到,但是涉及到數據量比較大或者是在資源比較緊張的系統中就顯得尤 -
分析php選擇排序法實現數組排序的方法
本文實例分析了php選擇排序法實現數組排序的.方法。分享給大家供大家參考。具體分析如下:選擇排序法的基本思路:直接用案例來說明吧,比如有一個數組$arr = array(2,6,3,9),從大到小排序。第一次大循環:它首先假設$arr[0]爲 -
C#排序算法之快速排序
C#排序算法怎樣快速排序呢?下面小編爲大家整理了C#排序算法之快速排序,希望能幫到大家! 快速排序實現:複製代碼 代碼如下:namespace QuickSort{class QuickSort{public static void Sort(int[] array){DoSort(array,0, -
C語言中使用快速排序算法對元素排序的實例
小心手,熱熔膠會燙主要材料:絲帶膠槍所需工具:熱膠槍製作步驟:第1步:折第2步:在折第3步:繼續折第4步:還是折第5步:翻過來折第6步:點膠第7步:重複四五六就好了 -
關於php堆排序實現原理與應用方法
這裏以php作爲描述語言較詳細講解堆排序原理,因保證程序可讀性,故不做優化,php程序中關於堆的一些概念如下:假設n爲當前數組的key則,n的父節點爲 n>>1 或者 n/2(整除);n的左子節點l= n<<1 或 l=n*2,n的右子節點r=(n<< -
C++ 排序插入排序詳解
插入排序的'基本思想是每次將一個待排序的記錄,按其關鍵字大小插入到前面已經排好序的子文件中的適當位置,直到全部記錄插入完成爲止。下面是小編分享的C++ 排序插入排序詳解,一起來看一下吧。常見的插入排序有插入排序 -
如何實現歸併排序
歸併排序的時間複雜度是:nlogn,如何實現歸併排序呢?下面是小編給大家提供的算法,大家可以參考閱讀,更多詳情請關注應屆畢業生考試網。歸併排序的.時間複雜度是:nlogn,主要是用到二路歸併排序,也就是把兩個有序集合合併爲一