二叉树学习之堆排序
認識堆是從堆排序開始的
根結點下標為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/
總結
- 上一篇: sparkSession常见参数设置
- 下一篇: Solr实战篇