堆排序完整代码带详解(续)
2009-10-06 16:52
246 查看
续上面,
上面的一个初始化构建堆和替换之后的构建堆是分开写的。
可以仔细看一下,初始化是从i=n/2..n开始到i=1..n开始构建的
而替换后是从i=1..n-1 ,i=1..n-2..构建的
只是构建的开始位置和结束位置不一样而已
所以完全可以合成一个函数,只是在构建堆的时候需要多写上一个从i=n/2到i=1的一个循环完成各个字数的构建。
完成代码如下:欢迎拍砖!
上面的一个初始化构建堆和替换之后的构建堆是分开写的。
可以仔细看一下,初始化是从i=n/2..n开始到i=1..n开始构建的
而替换后是从i=1..n-1 ,i=1..n-2..构建的
只是构建的开始位置和结束位置不一样而已
所以完全可以合成一个函数,只是在构建堆的时候需要多写上一个从i=n/2到i=1的一个循环完成各个字数的构建。
完成代码如下:欢迎拍砖!
#include <stdlib.h> #include <stdio.h> #define MAX_SIZE 20 typedef int ElemType; // 定义排序表 typedef struct HeapList { ElemType *keys; int length; }HeapList; // 初始化排序表 void InitHeapList(HeapList &L) { L.keys = (ElemType*)malloc(MAX_SIZE * sizeof(ElemType)); L.length = 6; int data[] = {38, 11, 9, 27, 96, 83}; for(int i = 0; i < 6; ++i) L.keys[i + 1] = data[i]; } // 打印排序表 void PrintHeapList(HeapList &L) { for(int i = 1; i <= L.length; ++i) printf("%5d", L.keys[i]); printf("/n"); } //初始化大堆 void CreateBigHeap(HeapList &L) { int middle = L.length/2; for(int i = middle; i > 0; i--) { if(((2*i + 1) > L.length) && (2*i <= L.length)) { // 当没有右字树的时候只判断根节点和左字树的大小进行调换 if(L.keys[i] < L.keys[2*i]) { L.keys[0] = L.keys[i]; L.keys[i] = L.keys[2*i]; L.keys[2*i] = L.keys[0]; } } if((2*i + 1) <= L.length) { // 左右子数都有 // 先比较左右字树哪个最大 int max = 2 * i; if(L.keys[2*i] < L.keys[2*i + 1])max++; if(L.keys[i] < L.keys[max]) { L.keys[0] = L.keys[i]; L.keys[i] = L.keys[max]; L.keys[max] = L.keys[0]; } } } } // 初始化大堆之后,每一次的对前N-1个进行再次大堆 void heapfy(HeapList &L, int end) { //此时出去root节点,其余的还是都符合大堆的,可以从头结点和他的子节点对比较,一直比到没有没有孩子结点或者满足大堆的时候停止 for(int i = 1; 2*i <= end; i *=2) { if(2*i + 1 <= end) { // 还是三者对比,然后把i更新到替换到得为之 int max = 2*i; if(L.keys[2*i] < L.keys[2*i + 1])max++; // 右字树最大,那么把该字树根节点和他对换吧 L.keys[0] = L.keys[i]; L.keys[i] = L.keys[max]; L.keys[max] = L.keys[0]; // 切记,更新i的位置 i = max; // 接下来跳出if,进入for的下一个循环,该此时继续把i的自树进行如上操作 } if(2*i + 1 > end && 2*i <= end) { // 只有左子树啦 if(L.keys[i] < L.keys[2*i]) { L.keys[0] = L.keys[i]; L.keys[i] = L.keys[2*i]; L.keys[2*i] = L.keys[0]; } } } } // 堆排序 void HeapSort(HeapList &L) { // 初始化一次大堆 CreateBigHeap(L); // 把第一个和最后一个调换一下 L.keys[0] = L.keys[1]; L.keys[1] = L.keys[L.length]; L.keys[L.length] = L.keys[0]; for(int i = L.length - 1; i > 0; --i) { heapfy(L, i); L.keys[0] = L.keys[1]; L.keys[1] = L.keys[i]; L.keys[i] = L.keys[0]; } } // 初始化大堆之后,每一次的对前N-1个进行再次大堆 void heapSortEvery(HeapList &L, int start, int end) { //此时出去root节点,其余的还是都符合大堆的,可以从头结点和他的子节点对比较,一直比到没有没有孩子结点或者满足大堆的时候停止 for(int i = start; 2*i <= end; i *=2) { if(2*i + 1 <= end) { // 还是三者对比,然后把i更新到替换到得为之 int max = 2*i; if(L.keys[2*i] < L.keys[2*i + 1])max++; // 右字树最大,那么把该字树根节点和他对换吧 L.keys[0] = L.keys[i]; L.keys[i] = L.keys[max]; L.keys[max] = L.keys[0]; // 切记,更新i的位置 i = max; // 接下来跳出if,进入for的下一个循环,该此时继续把i的自树进行如上操作 } if(2*i + 1 > end && 2*i <= end) { // 只有左子树啦 if(L.keys[i] < L.keys[2*i]) { L.keys[0] = L.keys[i]; L.keys[i] = L.keys[2*i]; L.keys[2*i] = L.keys[0]; } } } } void HeapSort_(HeapList &L) { // 先创建堆 for(int i = L.length/2; i > 0; --i) heapSortEvery(L, i, L.length); L.keys[0] = L.keys[1]; L.keys[1] = L.keys[L.length]; L.keys[L.length] = L.keys[0]; for(int j = L.length - 1; j > 0; --j) { heapSortEvery(L, 1, j); L.keys[0] = L.keys[1]; L.keys[1] = L.keys[j]; L.keys[j] = L.keys[0]; } } void main() { HeapList L; InitHeapList(L); PrintHeapList(L); HeapSort_(L); PrintHeapList(L); }
相关文章推荐
- 堆排序完整代码带详解
- 类型转换与字符串赋值、分割、合并、复制、比较、查询、翻转详解 (完整代码)
- WebView使用与JavaScript交互详解(附完整Demo代码)
- 基于JavaScript+HTML5 实现打地鼠小游戏逻辑流程图文详解(附完整代码)
- 实际搭建mybatis的代码及详解(完整自写版)
- 多输入路径MapReduce完整代码详解
- 算法导论学习--红黑树详解之删除(含完整红黑树代码)
- 自己动手实现jQuery Callbacks完整功能代码详解
- 详解C++中指针(*)、取地址(&)、解引用(*)与引用(&)的区别 (完整代码)
- 数据结构 - 堆排序(heap sort) 详解 及 代码(C++)
- RBtree详解之删除(含完整红黑树代码)
- 堆排序 完整代码与详细注释 C++语言实现
- 详解Java 网络IO编程总结(BIO、NIO、AIO均含完整实例代码)
- 自己动手实现jQuery Callbacks完整功能代码详解
- 详解多线程的两种实现方式以及4个线程,两个线程对j加1,两个线程对j减1完整代码。
- 【数据结构】二叉树之堆排序(完整代码)
- 排序算法之堆排序详解(附最大堆示例代码)
- MVC入门——经典MVC登录实例详解--附完整代码
- 堆排序原理详解和Java实现代码
- C# 堆排序 完整代码