二叉树学习之堆排序
来源:互联网 发布:java高级架构师 编辑:程序博客网 时间:2024/06/14 05:59
认识堆是从堆排序开始的
根结点下标为0时,下标为n的元素的子结点下标分别为2*n+1,2*n+2,其父结点下标为(n-1)/2
1、父结点的键值总是>=(<=)任何一个子结点的键值
2、每个结点的左右子树都是二叉堆
当父结点的键值总是小于或等于任何一个子节点的键值时为最小堆
堆的操作方法如下定义:
#ifndef _HEAP_CTL_H#define _HEAP_CTL_H#ifdef __cplusplusextern "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/
0 0
- 二叉树学习之堆排序
- 二叉树之堆排序
- 菜鸟学习数据结构之用堆排序理解二叉树
- 八大排序算法 之 堆排序(二叉树排序)
- 二叉树堆排序
- 数据结构之二叉堆、堆排序
- 数据结构之二叉堆(构建堆,堆排序)-(七)
- 数据结构之二叉堆(构建堆,堆排序)
- 数据结构学习之二叉堆
- 【数据结构】二叉树之堆排序(完整代码)
- 二叉树及堆排序
- 【二叉堆、堆排序】
- 二叉堆 & 堆排序
- 二叉堆 & 堆排序
- 二叉堆 & 堆排序
- 数据结构基础 之 二叉堆实现堆排序
- 算法学习之--堆排序
- heapSort - 堆排序 / 二叉堆
- Android 中遇到的一些警告 错误
- 为QT应用程序添加图标
- Android Layout 之 RelativeLayout之addRule()方法
- 程序猿之---C语言细节9(宏定义、max(a,b)宏定义细节、大小端判断、(int&)a什么意思)
- 兼容性
- 二叉树学习之堆排序
- 考生须知
- 2014年礼品行业的未来走向
- 云计算设计模式(二)——断路器模式
- jQuery中的$()
- 2014上海全国邀请赛 解题报告
- Policies/Binary Compatibility Issues With C++
- ERROR org.apache.hadoop.security.UserGroupInformation: PriviledgedActionException
- Enum示例