日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

二叉树学习之堆排序

發布時間:2024/8/23 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 二叉树学习之堆排序 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

認識堆是從堆排序開始的


二叉堆是完全二叉樹或者是近似完全二叉樹,堆存儲在數組中:

根結點下標為0時,下標為n的元素的子結點下標分別為2*n+1,2*n+2,其父結點下標為(n-1)/2


二叉堆的特性:
1、父結點的鍵值總是>=(<=)任何一個子結點的鍵值

2、每個結點的左右子樹都是二叉堆


當父結點的鍵值總是大于或等于任何一個子節點的鍵值時為最大堆

當父結點的鍵值總是小于或等于任何一個子節點的鍵值時為最小堆

的操作方法如下定義:

#ifndef _HEAP_CTL_H #define _HEAP_CTL_H#ifdef __cplusplus extern "C" { #endifvoid heapPprint(const char *info, int a[], int nLen); void swap(int *a, int *b);void buildMaxHeap(int *a, int hLen); void buildMinHeap(int *a, int hLen);void minHeapAddNumber(int *a, int *nLen, int newNum); void maxHeapAddNumber(int *a, int *nLen, int newNum); int minHeapDelNumber(int *a, int *nLen); int maxHeapDelNumber(int *a, int *nLen);void ascHeapSort(int *iArray,int nLen); void descHeapSort(int *iArray,int nLen);#ifdef __cplusplus } #endif #endif函數實現如下:

#include <stdio.h> #include "heapctl.h"static void __pprint(int a[], int i, int nLen) {printf("(");if (i < nLen) {printf("%d", a[i]);__pprint(a, i*2+1, nLen);__pprint(a, i*2+2,nLen);}printf(")"); }/***@brief 輸出堆用于tree工具來圖形化顯示**@params info 寫在前面的話*@params a 所要打印的數組*@params nLen 數組的長度*/ void heapPprint(const char *info, int a[], int nLen) {if (info)printf("%s", info);printf("\n\\tree");__pprint(a, 0, nLen);printf("\n"); }/***@brief 交換兩個數據**@params a 用以交換的第一個數據*@params b 用以交換的第二個數據*/ void swap(int *a, int *b) { #if 0//利用了輔助空間tmpint tmp = *a;*a = *b;*b = tmp; #endif#if 0//相加可能溢出*a += *b;*b = *a - *b;*a -= *b; #endif#if 1//異或運算A^B^B=A*a ^= *b;*b ^= *a;*a ^= *b; #endif }/***@brief 大頂堆調整**@params A 數組A*@params hLen*@params 需要調整的節點i*/ void maxHeapAdjust(int *a,int i,int size) //調整堆 {int lchild=2*i+1; //i的左孩子節點序號 int rchild=2*i+2; //i的右孩子節點序號 int max=i; //臨時變量 if(i <= size/2) //如果i是葉節點就不用進行調整 {if(lchild<size && a[lchild]>a[max]) {max=lchild;} if(rchild<size && a[rchild]>a[max]) {max=rchild;}if(max != i) {swap(&a[i], &a[max]);maxHeapAdjust(a,max,size); //避免調整之后以max為父節點的子樹不是堆 }} }/***@brief 構建大頂堆**@params a 數組a*@params hLen 數組元素的個數*/ void buildMaxHeap(int *a, int hLen) {int i;//堆類似完全二叉樹,nLen 為偶數://深度為2的節點數n2 = nLen>>1 -1, n1 = 1, n0 = nLen>>1;//nLen 為奇數, n2 = nLen/2, n1 = 0, n0 = nLen/2+1; //n0 = n2 + 1//從非葉節點最大序號位置調整, 值為size/2 for(i=hLen/2-1; i>=0; i--){maxHeapAdjust(a,i,hLen); } } /***@brief 小頂堆調整**@params A 數組A*@params hLen*@params 需要調整的節點i*/ void minHeapAdjust(int *a,int i,int size) //調整堆 {int lchild=2*i+1; //i的左孩子節點序號 int rchild=2*i+2; //i的右孩子節點序號 int max=i; //臨時變量 if(lchild<size && a[lchild]<a[max]) {max=lchild;} if(rchild<size && a[rchild]<a[max]) {max=rchild;}if(max != i) {swap(&a[i], &a[max]);minHeapAdjust(a, max, size); //避免調整之后以max為父節點的子樹不是堆 } }/***@brief 構建大頂堆**@params a 數組a*@params hLen 數組元素的個數*/ void buildMinHeap(int *a, int hLen) {int i;//堆類似完全二叉樹,nLen 為偶數://深度為2的節點數n2 = nLen>>1 -1, n1 = 1, n0 = nLen>>1;//nLen 為奇數, n2 = nLen/2, n1 = 0, n0 = nLen/2+1; //n0 = n2 + 1//從非葉節點最大序號位置調整, 值為size/2 for(i=hLen/2-1; i>=0; i--){minHeapAdjust(a,i,hLen); } } /***@brief 向小頂堆中插入數據**@params a 要插入數據的數組*@params nLen 數組元素長度指針, 插入后會自增*@params newNum 插入的元素值**1、將插入的數據放入數組的末尾*2、根據與其父節點的大小來調整小頂堆*/ void minHeapAddNumber(int *a, int *nLen, int newNum) {a[*nLen] = newNum; int j, i = *nLen;for (j = (i-1)/2;(j >= 0 && i != 0) && a[i] < a[j];i = j, j = (i-1)/2 )swap(&a[i], &a[j]);++*nLen; }/***@brief 向大頂堆中插入數據**@params a 要插入數據的數組*@params nLen 數組元素長度指針, 插入后會自增*@params newNum 插入的元素值**1、將插入的數據放入數組的末尾*2、根據與其父節點的大小關系調整大頂堆*/ void maxHeapAddNumber(int *a, int *nLen, int newNum) {a[*nLen] = newNum; int j, i = *nLen;for (j = (i-1)/2;(j >= 0 && i != 0) && a[i] > a[j];i = j, j = (i-1)/2 )swap(&a[i], &a[j]);++*nLen; }/***@brief 小頂堆的刪除操作,堆中每次都只能刪除第0個數據,**@params a 要刪除數據的數組*@params nLen 數組元素長度指針, 插入后會自減**1、將插入的數據放入數組的末尾*2、根據與其父節點的大小關系調整大頂堆*/ int minHeapDelNumber(int *a, int *nLen) {int newLen = *nLen - 1;swap(&a[0], &a[newLen]);minHeapAdjust(a, 0, newLen);*nLen = newLen;return a[newLen]; }int maxHeapDelNumber(int *a, int *nLen) {int newLen = *nLen - 1;swap(&a[0], &a[newLen]);maxHeapAdjust(a, 0, newLen);*nLen = newLen;return a[newLen]; }/***@brief 利用大頂堆進行升序排列**@params a 所要排序的數組名稱*@params nLen 數組中元素的個數*/ void ascHeapSort(int *a,int nLen) {int i;buildMaxHeap(a,nLen);for(i=nLen-1; i>=1; i--){swap(&a[0], &a[i]); //交換堆頂和最后一個元素,即每次將剩余元素中的最大者放到最后面 maxHeapAdjust(a, 0, i); //重新調整堆頂節點成為大頂堆} } /***@brief 利用小頂堆進行降序排列**@params a 所要排序的數組名稱*@params nLen 數組中元素的個數*/ void descHeapSort(int *iArray,int nLen) {int i;buildMinHeap(iArray, nLen);for(i=nLen-1; i>=1; i--) {swap(&iArray[0], &iArray[i]);minHeapAdjust(iArray, 0, i);} }

函數的實現方法與應用請自行參照注釋

或以下文檔

http://www.cnblogs.com/dolphin0520/archive/2011/10/06/2199741.html
http://blog.csdn.net/morewindows/article/details/6709644/

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的二叉树学习之堆排序的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。