亚洲精品中文字幕无乱码_久久亚洲精品无码AV大片_最新国产免费Av网址_国产精品3级片

C語言

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

時(shí)間:2024-09-15 17:36:39 C語言 我要投稿
  • 相關(guān)推薦

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

  堆排序(Heap Sort)只需要一個(gè)記錄大小的輔助空間,每個(gè)待排序的記錄僅占有一個(gè)存儲(chǔ)空間。下面小編為大家整理了內(nèi)部排序之堆排序的實(shí)現(xiàn),希望能幫到大家!

 。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)稱為堆頂,即:在一棵完全二叉樹中,所有非葉結(jié)點(diǎn)的值均小于(或均大于)左、右孩子的值。

  b)堆排序:是一種樹型選擇排序,特點(diǎn)是,在排序過程中,把R[1..n]看成是一個(gè)完全二叉樹的存儲(chǔ)結(jié)構(gòu),利用完全二叉樹雙親結(jié)點(diǎn)和孩子結(jié)點(diǎn)的內(nèi)在關(guān)系,在當(dāng)前無序區(qū)中選擇關(guān)鍵字最大(最。┑挠涗。

  (2)堆排序步驟:

  1、從k-1層的最右非葉結(jié)點(diǎn)開始,使關(guān)鍵字值大(或。┑挠涗浿鸩较蚨鏄涞纳蠈右苿(dòng),最大(或。╆P(guān)鍵字記錄成為樹的根結(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)整過程為“篩選”。

 。3)要解決的兩個(gè)問題:

 。、如何由一個(gè)無序序列建成一個(gè)堆;

 。病⑤敵鲆粋(gè)根結(jié)點(diǎn)后,如何將剩余元素調(diào)整成一個(gè)堆。

  將一個(gè)無序序列建成一個(gè)堆是一個(gè)反復(fù)“篩選”的過程。若將此序列看成是一個(gè)完全二叉樹,則最后一個(gè)非終端結(jié)點(diǎn)是第floor(n/2)個(gè)元素,由此“篩選”只需從第floor(n/2)個(gè)元素開始。

  堆排序中需一個(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語言代碼實(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è)無序序列建成一個(gè)大頂堆,將序列看成是一個(gè)完全二叉樹,則最后一個(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)開始存儲(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的無序序列成為一個(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è)無序序列建成一個(gè)大頂堆,將序列看成是一個(gè)完全二叉樹,則最后一個(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("%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); //打印堆排序結(jié)果

  system("pause");

  return 0;

  }

【內(nèi)部排序之堆排序的實(shí)現(xiàn)】相關(guān)文章:

java堆排序的算法思想的分析09-14

冒泡排序的原理以及java代碼實(shí)現(xiàn)08-17

JAVA簡(jiǎn)單選擇排序算法及實(shí)現(xiàn)10-02

C語言實(shí)現(xiàn)歸并排序算法實(shí)例09-18

冒泡排序算法原理及JAVA實(shí)現(xiàn)代碼方法10-16

C++實(shí)現(xiàn)自底向上的歸并排序算法09-09

Yii2如何實(shí)現(xiàn)跨mysql數(shù)據(jù)庫關(guān)聯(lián)查詢排序11-04

職稱英語輔導(dǎo)之句子中多個(gè)形容詞排序分析10-26

Java排序算法06-17

excel怎么排序07-26