码迷,mamicode.com
首页 > 编程语言 > 详细

算法之堆排序

时间:2014-11-07 23:31:06      阅读:276      评论:0      收藏:0      [点我收藏+]

标签:堆排序   算法   二叉树   java   

堆排序

堆:如果一棵完全二叉树的每个节点都大于(小于)它的子节点称之为堆。

    k >= 2k + 1 && k >= 2k + 2

  或者 k <= 2k + 1 && k <= 2k + 2

堆分:大顶堆和小顶堆。

完全二叉树:除了叶子节点所有的其他节点都有完整的左子树和右子数,除了最后一层的非叶子节点以外。


使用堆排序分两步:

1 建立一个无序的堆。

2 输出对顶元素,然后用最后一个元素代替堆顶元素,是之再成为一个堆。


比如: 3,22,8,11,55,1这样一个数使用堆排序的过程如下:

1. 先按顺序建立一颗完全二叉树:


bubuko.com,布布扣

按层级顺序填充数据,从最后一个非叶子节点看,是否满足堆的要求。

先从8开始,不满足堆的要求,和1换位。(该节点都必须大于或者小于左右子节点),我们按小顶堆排序,所以节点都应小于左右子节点。

bubuko.com,布布扣

再从22开始,不满足要求,和11换位。(若该节点小于左右时,和较小的子节点互换)

bubuko.com,布布扣

再从3开始,不满足要求,和1互换位置。

bubuko.com,布布扣

这样就建成了堆。所有的节点都不大于它的子节点。


2 第二阶段。

  从初始的堆中输出堆顶元素,然后将最后一个元素放到堆顶,然后在进行堆的定义置换。

  我们把较大元素从顶上落到底层的过程叫做------- 筛选。


  先输出1,然后将8置于堆顶

bubuko.com,布布扣

 然后按照步骤1的方式将其筛选成符合条件的堆,知道8落地为止,即筛选8。

先和3替换,8落地。符合堆

bubuko.com,布布扣

输出3,将55放置堆顶

bubuko.com,布布扣

然后筛选55得到如下

bubuko.com,布布扣

输出8,,22置堆顶

bubuko.com,布布扣

筛选22,将11置堆顶,

输出11,输出22,输出55

排序后应该是1,3, 8,11, 22, 55


我们可以用一维数组表示这个完全二叉树。

假如当前节点为K:

     那么父节点为:  (k - 1) / 2

    左孩子为: 2k  + 1

   有孩子为:2k + 2


其Java代码实现如下:

package andy.test;

/** 
 * @author Zhang,Tianyou
 * @version 2014年11月7日 下午10:32:31
 */

public class HeapSortTest {

	public static void main(String[] args) {
		int[] a = {3,22,8,11,55,1};
		heapSort(a);

	}
	
	private static void heapOne(int[] a, int n, int k) {
		//节点k进行筛选
		//a: 堆数据  n:堆中有效数据个数   k:筛选节点
		
		int k1 = 2*k + 1;//左子树序号
		int k2 = 2*k + 2;//右子数序号
		if(k1 >= n && k2 >= n)return ; //已经是叶子节点
		
		int a1 = Integer.MAX_VALUE;
		int a2 = Integer.MAX_VALUE;
		if(k1 < n)a1 = a[k1]; //左孩子值
		if(k2 < n)a2 = a[k2]; //右孩子值
		
		if(a[k] <= a1 && a[k] <= a2)return; //已符合堆的要求
		
		//找到左右孩子中最小的,和它交换
		if(a1 < a2){
			int temp = a[k];
			a[k] = a[k1];
			a[k1] = temp;
			heapOne(a, n, k1); //继续筛选子树
		}else{
			int temp = a[k];
			a[k] = a[k2];
			a[k2] = temp;
			heapOne(a, n, k2); //继续筛选子树
		}
		
	}
	
	static void heapSort(int[] a){
		//建立初始堆 
		//a.length     最后一个叶子节点   
		//a.length/ 2      最后一个非叶子节点
		for(int i = a.length / 2; i >= 0; i--)heapOne(a, a.length, i);
		
		//边输出堆顶元素,边调整
		int n = a.length;//剩余元素
		while(n > 0){
			System.out.print(a[0] + "  ");//输出堆顶元素
			a[0] = a[n - 1]; //最后一个元素置顶
			n--;
			heapOne(a, n, 0);//筛选第一个元素
			
		}
		System.out.println();
	}

	

}

输出结果为:

1  3  8  11  22  55  

算法之堆排序

标签:堆排序   算法   二叉树   java   

原文地址:http://blog.csdn.net/fengshizty/article/details/40899483

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!