堆排序-乡巴老都能懂
来源:互联网 发布:淘宝客推广的入口 编辑:程序博客网 时间:2024/06/04 20:14
堆排序-乡巴老都能懂
什么是堆排序?
堆排序是由 :大顶堆或者小顶堆 堆调整 堆排序 这三个部分组成;本文介绍的思路顺序是:创建对调整函数 创建大顶堆 然后堆排序;什么是大顶堆?
大顶堆 一个树根 下分两个树杈 ;就像一棵树 就是大顶堆,树根(根节点)什么居然问我树根? 没有树根 你树杈怎么长出来的,没有树杈怎么长叶子?树杈(叶节点) ? 有些人想起了去掏鸟蛋,我们的树有些特别 比较好爬,不会划伤你,因为什么呢? 树杈就是树根的分支 ,树根就2个树杈,一个树杈下就两个小树杈,你想要多大 它就分多少我家树没有树杈?我晕,你没有树杈 就一个树根 你家树 估计是拴牛用的, 那你就不需要这么麻烦用程序来计算了,就一个怎么排序啊跟我大顶堆有什么关系?因为大顶堆就是将数据以树的机构摆放起来,怎么将数据已树的结构摆放起来啊? 需要堆调整啊?来了,请看下面。后续的代码都会注释 呈上什么树堆调整 ?
已数组为例,将数组 摆放成树的结构int n =9; 多少个数组元素 int index 从哪个元素开始分配孩子int Lchlid = index *2 + 1;//左孩子 孩子分配方法,int Rchlid = index *2 + 2 ;//右孩子到底怎么摆放 ?1.首先你需要直到摆放多少个的数据(数组元素个数)2.分配你的孩子,就像上面的左孩子右孩子3. 我分配多少个不能一辈子总是分配吧, 我说过一个树结构至少要有两个树杈,左孩子的下标>n 超出右孩子右孩子也不会存在, 所以要找到他们的条件 (调整的条件)(终止的条件3)// 1 2 3 4 5 6 7 8 9//根 左 右//1 3 4我们将1作为根,计算后它的L孩子是3,R孩子是4 (调整的条件1)//2 5 6//3 7 8//4 9 情况2:下标4分配孩子 有左孩子 ,右孩子不符合条件了( 调整的条件2)//5 (11 12) return情况1:下标5的孩子是 左11 右12 而数组个数是9,超出9就下标越界了,这种情况是我们(终止的条件)情况1 左孩子(L)> n return 左孩子不存在,右孩子自然也没有 我们就不调整了,返回情况2 左孩子(L)< n && 右孩子> n 了 只有左孩子情况3 左孩子(L)< n && 右孩子 < n 左右孩子都存在 我们就开始调整堆调整:将数值大的放到根节点上if 左孩子>nreturn;if 根<左孩子 交换else 左孩子<右孩子交换递归 将左孩子 作为下次的根节点参数传入 将它后面的分支调整递归 将右孩子 作为下次的根节点参数传入 将它后面的分支调整至此堆调整函数完毕 作用:(调整一个根和孩子) 这个堆调整怎么用呢? 往下看创建大顶堆:就是循环 对每一个元素进行调整,for(i-n-1;i>=0;i--)调用堆调整大顶堆完毕 作用(将数组都调整完 ,并且最大值挑选出来放在第一个根上)堆排序 :调用 大顶堆一次将最大值交换给最后面,最后面不参与新的排序,N-1 直到 循环到下标1 停止循环堆排序完毕作用(堆调整完的值放到最后,最后不参与调整,排序完成)代码实例:
#include <stdio.h>#include <stdlib.h>#include <time.h>//堆调整: 大顶堆,//参数:arr 数组,n 数组元素个数,index是需要调整的下标//void adjust(int arr[], int n,int index){ int Lchlid = index *2 + 1;//左孩子 int Rchlid = index *2 + 2 ;//右孩子 int tmp ; //交换// 1 2 3 4 5 6 7 8 9 10//根 左 右//1 3 4//2 5 6//3 7 8//4 9 10//5 (11 12) return//如何判断有没有孩子 //方法:通过判断下标是不是在数组个数的范围内 //举例:下标5的孩子是 左11 右12 而数组个数是10,超出10就不存在孩子 //判断右孩子是否存在: //1.右孩子的下标>左孩子 2.左孩子存在并且 右孩子下标不能超出元素个数n //Rchlid >= n 就说明越界了,就不存在//没有左孩子,右孩子也不会存在,就不调整(不成立的条件返回) if(Lchlid >= n) return; //有左孩子的情况下 则进入下面的判断 //在以上条件下, //1.右孩子不存在 或者 2.左孩子的值比右孩子大值 if(Rchlid >= n || arr[Lchlid] >arr[Rchlid]) {//比较根节点和左孩子的值:(~~有些人分不清下标和值了), if(arr[index] < arr[Lchlid])//根节点小于左孩子节点 { tmp = arr[index]; arr[index] = arr[Lchlid]; arr[Lchlid] = tmp ; //对调整后的左孩子节点继续进行堆调整 //如果左孩子<n 就一直对左孩子的左孩子进行调整,直到条件终止,即>n adjust(arr , n, Lchlid); } return ; } //有左孩子也有右孩子 比较左右孩子调整 //思路:将值大的放在 左孩子身上 //递归调用 判断右孩子的孩子 else //有右孩子 并且 右孩子比左孩子大 { //比较根节点和右孩子, if(arr[index] < arr[Rchlid])//根节点小于右孩子节点 { tmp = arr[index]; arr[index] = arr[Rchlid]; arr[Rchlid] = tmp ; //对调整后的右孩子节点继续进行堆调整 adjust(arr , n, Rchlid); } return ; }}//2.创建一个大顶堆void createHeap (int arr[] , int n){ int i; //从后到前 对每一个元素进行调整 for (i = n-1; i>=0; i--) {//比如 i= n=10 没有孩子 // i= 9 没有孩子 i= 8 没有孩子 // i = 4 左 9 右10 开始调整孩子 adjust(arr,n,i); }}//3.堆排序void heapSort (int arr[] ,int n){ int tmp; //创建大顶堆 createHeap(arr,n); //最大值在下标0,将下标0和 最后下标n-1交换 最大的放到最后了 // do { //堆顶节点和最后节点交换 tmp = arr[0]; arr[0] = arr[n - 1]; arr[n-1] = tmp; n--; //对堆顶节点进行调整 adjust( arr , n , 0); //将最大值又放到了最上面,下标0,直到n=1最后一次循环 }while(n>1);}//打印数组void PrintArray(int arr[] , int n){ int i; for (i = 0 ;i<n; i++) printf("%d ",arr[i]); printf("\n*****************************\n");}int main(){ int arr[10]; int i; srand((unsigned)time(NULL)); for(i = 0 ; i < 10; i++) arr[i]= rand() % 100; PrintArray(arr, 10); heapSort(arr,10); PrintArray(arr,10); return 0;}
阅读全文
0 0
- 堆排序-乡巴老都能懂
- 堆及堆排序
- 堆/堆排序特点
- 【二叉堆、堆排序】
- 二叉堆 & 堆排序
- 二叉堆 & 堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆和堆排序
- 堆排序(最大堆)
- 堆和堆排序
- 堆和堆排序
- 堆及堆排序
- 堆和堆排序
- 【D3】D3 使用教程(1)-数据
- springmvc 406错误
- 破解VBA密码
- 依赖及权限
- [Git痛点讲解 : 不断完善中]
- 堆排序-乡巴老都能懂
- 使用vue-cli打包过程中的步骤以及问题
- 数据结构实验之查找五:平方之哈希表
- input输入框autofill自动变成黄色
- wake-sleep 算法的个人理解
- 基于Dragonboard 410c的指纹锁(六)
- linux与andriod区别
- 哎~ 下个月的口粮
- 【vs调试】PDB文件:每个开发人员都必须知道的