排序算法之堆排序
2016-04-13 22:01
337 查看
介绍堆排序算法之前必须知道“堆”这种数据结构,堆可近似看成是一个完全二叉树,不同的是用数组中的元素从上到下,从左到右填充该树。
堆可分为最大堆和最小堆(查看定义),堆排序算法就是建立在最大堆或者最小堆基础上,通过不断取出堆顶元素,将剩下n-1个元素重新建堆,如此循环获得有序序列。所以关键在于如何建最大堆/最小堆和如何调整剩余元素为新堆。(不上图了,大家看其他博客)
堆排序用在大数据量比较有效,同时不仅用于排序,推广到取最值的引用中,例如进程调度:选取优先级最高的进程,时间调度中:取执行时间最短或者等待时间最长等等。
1.堆的存储
堆一般以数组的形式表示,i节点的父节点是(i-1)/2,子节点是2*i +1和2*i+2,例如节点0的子节点是1和2。
2.堆的操作
堆操作包括堆的插入(插入堆尾),删除及删除后调整(删除堆顶,重新调整)。堆排序是建堆后取得堆顶元素,所以,重点对删除及删除后调整进行操作。
建堆用到递归思想,堆的调整是自下往上,把i节点和它的两个子节点2*i+1和2*i+2进行比较,找出最大的节点存到i节点中,i从树的最后一个非叶子节点开始往上取,每一趟便找出最大值,如此往复。
3.实现:(VC6.0验证通过)
后续总结:堆排序首先建造堆(从下往上),取堆顶元素后,调整堆(从上往下)。建造堆时,从最后一个非叶子节点开始,与子节点比较,将最大值存储到i节点中,以此往上,构造出最大堆;将堆顶元素与堆尾元素交换后,对余下元素(除最大元素)用同样方法调整,建造新的堆…
堆可分为最大堆和最小堆(查看定义),堆排序算法就是建立在最大堆或者最小堆基础上,通过不断取出堆顶元素,将剩下n-1个元素重新建堆,如此循环获得有序序列。所以关键在于如何建最大堆/最小堆和如何调整剩余元素为新堆。(不上图了,大家看其他博客)
堆排序用在大数据量比较有效,同时不仅用于排序,推广到取最值的引用中,例如进程调度:选取优先级最高的进程,时间调度中:取执行时间最短或者等待时间最长等等。
1.堆的存储
堆一般以数组的形式表示,i节点的父节点是(i-1)/2,子节点是2*i +1和2*i+2,例如节点0的子节点是1和2。
2.堆的操作
堆操作包括堆的插入(插入堆尾),删除及删除后调整(删除堆顶,重新调整)。堆排序是建堆后取得堆顶元素,所以,重点对删除及删除后调整进行操作。
建堆用到递归思想,堆的调整是自下往上,把i节点和它的两个子节点2*i+1和2*i+2进行比较,找出最大的节点存到i节点中,i从树的最后一个非叶子节点开始往上取,每一趟便找出最大值,如此往复。
3.实现:(VC6.0验证通过)
#include<stdio.h> //i节点及2*i+1与2*i+2三节点找出最大值,i==start void Adjust(int a[],int start,int len) { int i,max,tmp; i=start; max=i; while((2*i+1)<len || (2*i+2)<len)//循环使子树都为堆 { if((2*i+1)<len && a[2*i+1]>a[i]) max=2*i+1; //右子节点存在的话,左子节点一定存在,所以与前两个的最大值比 if((2*i+2)<len && a[2*i+2]>a[max]) max=2*i+2; /*****选取三个数中的最大值*************** if((2*i+1)<len && (2*i+2)<len) { if (a[2*i+2]<a[2*i+1]) max=2*i+1; else max=2*i+2; }//有bug,如果只有一个子节点呢 **************************************/ if(a[max]>a[i]) { tmp=a[max]; a[max]=a[i]; a[i]=tmp; i=max; } else break; } } void Build(int a[],int len)//从下往上构造最大树 { int i; for(i=len/2-1;i>=0;i--)//len/2-1为最后一个非叶子结点 { Adjust(a,i,len); } } void Heapsort(int a[],int len)//将数的根节点与尾节点交换后,重新构造树 { int i,tmp; Build(a,len); for(i=len-1;i>=0;i--) { tmp=a[i]; a[i]=a[0]; a[0]=tmp;//交换第一个值与最后一个值 Adjust(a,0,i-1);//重新调整剩下的n-1个数 } } //打印数组 print(int a[],int len) { int i; for(i=0;i<len;i++) printf("%d ",a[i]); printf("\n"); } void main() { int a[]={5,3,4,2,6,8,1,7}; print(a,8); Heapsort(a,8); print(a,8); }
后续总结:堆排序首先建造堆(从下往上),取堆顶元素后,调整堆(从上往下)。建造堆时,从最后一个非叶子节点开始,与子节点比较,将最大值存储到i节点中,以此往上,构造出最大堆;将堆顶元素与堆尾元素交换后,对余下元素(除最大元素)用同样方法调整,建造新的堆…
相关文章推荐
- MySQL入门很简单: 1 数据库概述
- STL源码----容器与算法
- Html5 离线应用缓存application Cache
- 一个差点被IoGetDeviceObjectPointer搞死的菜鸟
- struts2开发3--动态得到要访问Action方法的3种方法
- Eclipse中设置VM参数
- 小谈Java Enum的多态性
- Eclipse中设置VM参数
- SSM整合 错误收集之 listener
- linux内核调试技巧之一 dump_stack
- C# Winform工程省市县三级行政区联动 --XML
- 数字:
- TopCoder SRM687 div1 500
- JavaScript设计模式返璞归真
- LeetCode *** 77. Combinations
- VMware虚拟linux系统时与主机共享文件夹
- 第3周 C语言及程序设计初步例程-39 求素数算法
- hive 配置参数说明
- 软件工程_东师站_第六周作业
- struts2的action从request获取参数值的几种方式