欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

內(nèi)部排序之堆排序的實(shí)現(xiàn)詳解

 更新時(shí)間:2013年05月24日 14:56:36   作者:  
本篇文章是對(duì)堆排序的實(shí)現(xiàn)進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
堆排序(Heap Sort)只需要一個(gè)記錄大小的輔助空間,每個(gè)待排序的記錄僅占有一個(gè)存儲(chǔ)空間。
(1)基本概念
a)堆:設(shè)有n個(gè)元素的序列:
{k1, k2, ..., kn}
對(duì)所有的i=1,2,...,(int)(n/2),當(dāng)滿足下面關(guān)系:
                                                                  ki≤k2i,ki≤k2i+1
                                                  或            ki≥k2i,ki≥k2i+1
這樣的序列稱為堆。
堆的兩種類型:
   根結(jié)點(diǎn)最小的堆----小根堆。
   根結(jié)點(diǎn)最大的堆----大根堆。
根結(jié)點(diǎn)稱為堆頂,即:在一棵完全二叉樹(shù)中,所有非葉結(jié)點(diǎn)的值均小于(或均大于)左、右孩子的值。
b)堆排序:是一種樹(shù)型選擇排序,特點(diǎn)是,在排序過(guò)程中,把R[1..n]看成是一個(gè)完全二叉樹(shù)的存儲(chǔ)結(jié)構(gòu),利用完全二叉樹(shù)雙親結(jié)點(diǎn)和孩子結(jié)點(diǎn)的內(nèi)在關(guān)系,在當(dāng)前無(wú)序區(qū)中選擇關(guān)鍵字最大(最?。┑挠涗?。
2)堆排序步驟:
1、從k-1層的最右非葉結(jié)點(diǎn)開(kāi)始,使關(guān)鍵字值大(或?。┑挠涗浿鸩较蚨鏄?shù)的上層移動(dòng),最大(或小)關(guān)鍵字記錄成為樹(shù)的根結(jié)點(diǎn),使其成為堆。
2、逐步輸出根結(jié)點(diǎn),令r[1]=r[i](i=n,,n-1,...,2),在將剩余結(jié)點(diǎn)調(diào)整成堆。直到輸出所有結(jié)點(diǎn)。我們稱這個(gè)自堆頂?shù)饺~子的調(diào)整過(guò)程為“篩選”。
(3)要解決的兩個(gè)問(wèn)題:
1、如何由一個(gè)無(wú)序序列建成一個(gè)堆;
2、輸出一個(gè)根結(jié)點(diǎn)后,如何將剩余元素調(diào)整成一個(gè)堆。
將一個(gè)無(wú)序序列建成一個(gè)堆是一個(gè)反復(fù)“篩選”的過(guò)程。若將此序列看成是一個(gè)完全二叉樹(shù),則最后一個(gè)非終端結(jié)點(diǎn)是第floor(n/2)個(gè)元素,由此“篩選”只需從第floor(n/2)個(gè)元素開(kāi)始。
堆排序中需一個(gè)記錄大小的輔助空間,每個(gè)待排的記錄僅占有一個(gè)存儲(chǔ)空間。堆排序方法當(dāng)記錄較少時(shí),不值得提倡。當(dāng)n很大時(shí),效率很高。堆排序是不穩(wěn)定的。
堆排序的算法和篩選的算法如第二節(jié)所示。為使排序結(jié)果是非遞減有序排列,我們?cè)谂判蛩惴ㄖ邢冉ㄒ粋€(gè)“大頂堆”,即先選得一個(gè)關(guān)鍵字為最大的記錄并與序列中最后一個(gè)記錄交換,然后對(duì)序列中前n-1個(gè)記錄進(jìn)行篩選,重新將它調(diào)整為一個(gè)“大頂堆”,然后將選得的一個(gè)關(guān)鍵字為最大的記錄(也就是第一個(gè)元素)與當(dāng)前最后一個(gè)記錄交換(全局看是第n-1個(gè)),如此往復(fù),直到排序結(jié)束。由到,篩選應(yīng)按關(guān)鍵字較大的孩子結(jié)點(diǎn)向下進(jìn)行。
堆排序的算法描述如下: 

 

用C語(yǔ)言代碼實(shí)現(xiàn)如下:
復(fù)制代碼 代碼如下:

#include "iostream"
using namespace std;
#define MAXSIZE 20
typedef struct
{
 int key;
 //其他數(shù)據(jù)信息
}RedType;
typedef struct
{
 RedType r[MAXSIZE+1];
 int length;
}Sqlist;
typedef Sqlist HeapType;  //堆采用順序表存儲(chǔ)表示
void HeapAdjust(HeapType &H,int s,int m)   //已知H.r[s...m]中記錄的關(guān)鍵字出H.r[s].key之外均滿足堆的定義,本函數(shù)調(diào)整H.r[s]的關(guān)鍵字,使H.r[s...m]成為一個(gè)大頂堆(對(duì)其中記錄的關(guān)鍵字而言)
{
 int j;
 RedType rc;
 rc=H.r[s];
 for(j=2*s;j<=m;j*=2)   //沿key較大的孩子結(jié)點(diǎn)向下篩選
 {
  if(j<m && (H.r[j].key<H.r[j+1].key))     //j為key較大的記錄的下標(biāo)
   ++j;
  if(rc.key>=H.r[j].key)           //rc應(yīng)插入在位置s上
   break;
  H.r[s]=H.r[j];      //將左、右孩子較大的結(jié)點(diǎn)與父節(jié)點(diǎn)進(jìn)行交換,建成大頂堆
  s=j;
 }
 H.r[s]=rc;             //插入
}
void HeapSort(HeapType &H)      //對(duì)順序表H進(jìn)行堆排序
{
 int i;
 for(i=H.length/2;i>0;--i)   //由一個(gè)無(wú)序序列建成一個(gè)大頂堆,將序列看成是一個(gè)完全二叉樹(shù),則最后一個(gè)非終端節(jié)點(diǎn)是第n/2個(gè)元素
  HeapAdjust(H,i,H.length);
 for(i=H.length;i>1;--i)
 {
  H.r[0]=H.r[1];   //將堆頂記錄和當(dāng)前未經(jīng)排序的子序列H.r[1...i]中最后一個(gè)記錄相互交換
  H.r[1]=H.r[i];
  H.r[i]=H.r[0];
  HeapAdjust(H,1,i-1);    //將H.r[1...i-1]重新調(diào)整為大頂堆
 }
}//HeapSort
void InputL(Sqlist &L)
{
 int i;
 printf("Please input the length:");
 scanf("%d",&L.length);
 printf("Please input the data needed to sort:\n");
 for(i=1;i<=L.length;i++)    //從數(shù)組的第1個(gè)下標(biāo)開(kāi)始存儲(chǔ),第0個(gè)下標(biāo)作為一個(gè)用于交換的臨時(shí)變量
  scanf("%d",&L.r[i].key);
}
void OutputL(Sqlist &L)
{
 int i;
 printf("The data after sorting is:\n");
 for(i=1;i<=L.length;i++)
  printf("%d ",L.r[i].key);
 printf("\n");
}
int main(void)
{
 Sqlist H;
 InputL(H);
 HeapSort(H);
 OutputL(H);
 system("pause");
 return 0;
}

不使用上面的結(jié)構(gòu)體的另外一種方法如下:
復(fù)制代碼 代碼如下:

/*
*堆排序
*/
#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)     //對(duì)堆進(jìn)行調(diào)整,使下標(biāo)從root到len的無(wú)序序列成為一個(gè)大頂堆
{
 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--)    //由一個(gè)無(wú)序序列建成一個(gè)大頂堆,將序列看成是一個(gè)完全二叉樹(shù),則最后一個(gè)非終端節(jié)點(diǎn)是第len/2個(gè)元素
 {
  heap_adjust(heap,i,len);
 }
 for(i=len;i>=1;i--)
 {
  mySwap(heap+i,heap+1);    //將堆頂記錄與最后一個(gè)記錄相互交換
  heap_adjust(heap,1,i-1);   //將下標(biāo)為1~i-1的記錄重新調(diào)整為大頂堆
 }
}
void print_array(int *array,int n)
{
 int k;
 for(k=1;k<n+1;k++)
 {
  printf("%d\t",array[k]);
 }
}
int main(void)
{
 man_input(array);
 heapSort(array,N);
 printf("\nAfter sorted by the heap_sort algorithm:\n");       
 print_array(array,N);   //打印堆排序結(jié)果
 system("pause");
 return 0;
}

相關(guān)文章

  • C++?繼承的范例講解

    C++?繼承的范例講解

    繼承是C++面向?qū)ο缶幊讨械囊婚T(mén)。繼承是子類繼承父類的特征和行為,或者是繼承父類得方法,使的子類具有父類得的特性和行為。重寫(xiě)是子類對(duì)父類的允許訪問(wèn)的方法實(shí)行的過(guò)程進(jìn)行重新編寫(xiě),返回值和形參都不能改變。就是對(duì)原本的父類進(jìn)行重新編寫(xiě),但是外部接口不能被重寫(xiě)
    2022-06-06
  • 詳解C++編程中標(biāo)記語(yǔ)句與復(fù)合語(yǔ)句的寫(xiě)法

    詳解C++編程中標(biāo)記語(yǔ)句與復(fù)合語(yǔ)句的寫(xiě)法

    這篇文章主要介紹了C++編程中標(biāo)記語(yǔ)句與復(fù)合語(yǔ)句的寫(xiě)法,是C++入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2016-01-01
  • C語(yǔ)言編程中生成隨機(jī)數(shù)的入門(mén)教程

    C語(yǔ)言編程中生成隨機(jī)數(shù)的入門(mén)教程

    這篇文章主要介紹了C語(yǔ)言編程中生成隨機(jī)數(shù)的入門(mén)教程,包括利用rand()函數(shù)來(lái)編寫(xiě)隨機(jī)數(shù)生成器的示例,要的朋友可以參考下
    2015-12-12
  • C++ OpenCV實(shí)戰(zhàn)之圖像全景拼接

    C++ OpenCV實(shí)戰(zhàn)之圖像全景拼接

    本文主要介紹了如何使用OpenCV C++ 進(jìn)行圖像全景拼接,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)OpenCV有一定的幫助,感興趣的可以了解一下
    2022-01-01
  • C++獲取項(xiàng)目路徑的兩種方式詳解

    C++獲取項(xiàng)目路徑的兩種方式詳解

    這篇文章主要介紹了C++獲取項(xiàng)目路徑的兩種方式的相關(guān)資料,需要的朋友可以參考下,希望能夠給你帶來(lái)幫助
    2021-10-10
  • C++實(shí)現(xiàn)日期類的方法詳解

    C++實(shí)現(xiàn)日期類的方法詳解

    這篇文章主要給大家介紹了C++實(shí)現(xiàn)日期類的方法,文中通過(guò)代碼示例給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2024-01-01
  • C語(yǔ)言的數(shù)組指針與函數(shù)指針詳解

    C語(yǔ)言的數(shù)組指針與函數(shù)指針詳解

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言的數(shù)組指針與函數(shù)指針,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-03-03
  • Qt5.9畫(huà)五角星的方法

    Qt5.9畫(huà)五角星的方法

    這篇文章主要為大家詳細(xì)介紹了Qt5.9畫(huà)五角星的方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-07-07
  • C++實(shí)現(xiàn)簡(jiǎn)易通訊錄功能

    C++實(shí)現(xiàn)簡(jiǎn)易通訊錄功能

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)簡(jiǎn)易通訊錄功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • 一文詳解C++11中的lambda函數(shù)

    一文詳解C++11中的lambda函數(shù)

    小編可以明確告訴大家:lambda函數(shù)是C++11中最重要的,使用最廣泛的,最具現(xiàn)代風(fēng)格的內(nèi)容,lambda函數(shù)的出現(xiàn)改變了C++編程的思維方式。所以快和小編學(xué)習(xí)一下C++11中l(wèi)ambda函數(shù)的使用吧
    2023-02-02

最新評(píng)論