您的位置:首页 > 编程语言 > Java开发

Java实现排序算法2:堆排序

2016-03-30 23:31 288 查看
说一下堆排序,关于堆排序则稍显复杂:

首先先说一些概念:

1.优先队列:在多用户环境中,操作系统调度程序必须决定在若干个进程中运行哪个进程,一般一个进程只被允许运行一个固定的时间片。一种算法是使用一个队列。开始时作业被放到队列末尾。调度程序将反复提取队列中的第一个作业并运行它,直到运行完毕,或者该作业的时间片用完,并在作业未运行完毕时把它放到队列的末尾。显然这种方式不合适。因为有些很短的作业由于一味的等待而花费很长时间处理。一般来说短的作业要尽可能结束。或者有些作业不短但是很重要,也应该有优先权。所以这些情况下就需要一类特殊的队列,称之为优先队列。

实现优先队列有几种明显的方式:一种是使用简单链表在表头以O(1)插入,然后以O(N)时间遍历链表删除最小元;或者让链表始终保持排序状态,那么插入代价就是O(N),而删除最小元是O(1)时间。但前者稍微更好,这个自己体会(删除最小元的操作不多于插入操作)。另一种方式是使用二叉查找树,这两种方式的时间都是O(logN),但会严重影响平衡,加深深度,不过可以使用平衡树来解决,以后会在数据结构的笔记里解释。

二叉堆将会是一个更好的解决办法:

不做太多介绍,简单说一下二叉堆的特点:

绝大多数情况下,二叉堆就是堆,还有其它的比如斐波那契堆,使用很少,我也没学过,以后会做相关笔记。堆就是完全二叉树,因此基于完全二叉树特点,因此可以用数组而不需要链来实现。而且遍历该树的操作十分简单。快速执行的性质是堆序性质,父节点的关键字总是小于子节点的

关键字,因此findmin的时间是常数时间,一看便知。关于堆的插入和删除就不做过多解释,这里主要讨论的是排序。

了解了基本概念,直接说堆排序的思路:分两步走:建堆,然后把根节点和最后一个节点交换,

然后继续建堆,对除了最后一个节点外的其他部分建堆。

首先就是建堆,这里我是使用的上滤来完成的:

public static void buildHeap(){
int[]  a = {10,8,18,5,6,12};
int  guard = a.length - 1;
for(int i = (guard - 1) / 2; i >= 0; i --){
while((2*i+1) <= guard){
int biggerIndex = 2*i+1;
if((2*i+1) <guard){
if(a[2*i+1]<a[2*i+2]){
biggerIndex ++;
}
}
if(a[i] < a[biggerIndex]){
int temp = a[i];
a[i] = a[biggerIndex];
a[biggerIndex] =temp;
}else{
break;
}

}
System.out.println(Arrays.toString(a));
}
System.out.println(Arrays.toString(a));
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: