堆排序 java

堆排序是使用二叉树模型,建立最大堆或最小堆,将最大值或最小值上浮,降低遍历次数,增加排序效率的一种解决方法。

由于堆排序时使用的是完全二叉模型,所以可以使用数组进行表示。

在使用堆排序时,需要使用到完全二叉树的一些公式,如父节点n/2-1,左子节点2i+1,右子节点2i+2,叶子节点(>size/2)等。具体见代码。

 

1、首先定义堆模型的一些常用操作接口。

 

package cn.dream.sort;

public interface IHeapSort {

	/**
	 * 获取父节点的位置
	 * 完全二叉树父节点位置在(n-1)/2处
	 * @param i
	 * @return
	 */
	int getParent(int i);
	
	/**
	 * 获取左子位置
	 * 完全二叉树左子节点在2*i+1处
	 * @param i
	 * @return
	 */
	int getLeftChild(int i);
	
	/**
	 * 获取右子位置
	 * 完全二叉树右子节点在左子节点的后面(2*i+1)+1
	 * @param i
	 * @return
	 */
	int getRightChild(int i);
	
	/**
	 * 建堆
	 * 从n/2-1处开始调整树结构,因为从n/2处都是叶子节点,不需要调整
	 * @param a
	 * @param size
	 */
	int[] buildHeap(int[] a, int size);
	
	/**
	 * 调整堆
	 * 通过对堆的调整,使其满足堆结构的要求,最大值上浮或最小值上浮。
	 * 对于任一节点进行调整时:
	 * 1、最大堆:如果该节点比(左右子节点最大值)小,交换该节点和最大值位置,然后调整树
	 * 2、最小堆:如果该节点比(左右子节点最小值)大,交换该节点和最小值位置,然后调整树
	 * @param a
	 * @param i
	 * @param size
	 */
	int[] adjustHeap(int[] a, int i, int size);
	
	/**
	 * 堆排序
	 * 1、最小堆:
	 * 方法一:执行遍历{将根节点(min)取出,构建树}
	 * 方法二:执行遍历{将根节点(min)和最后一个节点(数组最后一位)交换,将参与构建的数组长度-1(移动size的index),重新构建树结构},最后倒序输出
	 * 2、最大堆:执行遍历{将根节点(max)和最后一个节点(数组最后一位)交换,将参与构建的数组长度-1(移动size的index),重新构建树结构}
	 * @param a
	 * @param size
	 */
	int[] sortHeap(int[] a, int size);
	
}

 

 

然后分别建立最大堆和最小堆,进行编码测试

最小堆

 

package cn.dream.sort;

import java.util.Arrays;

public class MinHeapSortImpl implements IHeapSort {

	@Override
	public int getParent(int i) {
		return (int) (i - 1) / 2;
	}

	@Override
	public int getLeftChild(int i) {
		return 2 * i + 1;
	}

	@Override
	public int getRightChild(int i) {
		return 2 * i + 2;
	}

	@Override
	public int[] buildHeap(int[] a, int size) {
		for (int i = (size - 2) / 2; i >= 0; i--) {
			adjustHeap(a, i, size);
		}
		return a;
	}

	@Override
	public int[] adjustHeap(int[] a, int i, int size) {
		int min = i;
		int temp = a[i];
		int left = getLeftChild(i);
		int right = getRightChild(i);

		if (left < size && a[left] < temp) {
			min = left;
		}

		if (right < size && a[right] < a[min]) {
			min = right;
		}

		if (min != i) {
			a[i] = a[min];
			a[min] = temp;
			adjustHeap(a, min, size);
		}
		return a;
	}

	@Override
	public int[] sortHeap(int[] a, int size) {
		int[] b = new int[a.length];
		int i = 0;
		while(size>0) {
			b[i] = a[0];
			a[0] = a[size - 1];
			--size;
			adjustHeap(a, 0, size);
			
			i++;
		}
		return b;
	}

	public static void main(String[] args) {
		int[] arr = { 53, 4, 24, 47, 41, 97, 13, 83, 12, 35, 11, 15, 41, 18,
				68, 49, 36, 52, 9, 45, 0, 38, 36, 82, 76, 22, 44, 35, 34, 81,
				94, 70, 88, 30, 42, 45, 55, 75, 93, 57, 74, 0, 77, 64, 93, 58,
				15, 62, 13, 49, 60, 21, 3, 66, 15, 74, 48, 96, 52, 56, 63, 73,
				85, 44, 39, 42, 98, 38, 17, 81, 7, 60, 86, 79, 63, 66, 17, 78,
				78, 90, 23, 92, 79, 21, 80, 71, 6, 70, 59, 25, 41, 11, 64, 60,
				62, 51, 93, 46, 18, 31 };

		long startTime = System.currentTimeMillis();

		IHeapSort heapSort = new MinHeapSortImpl();

		System.out.println("测试最小堆的根节点是否最小值:");
		heapSort.buildHeap(arr, arr.length);
		System.out.println("root is:" + arr[0]);

		System.out.println("测试最小堆是否已经排序:");
		System.out.println(Arrays.toString(arr));

		System.out.println("排序:");
		int[] heap = heapSort.sortHeap(arr, arr.length);
		System.out.println(Arrays.toString(heap));

		System.out.println((System.currentTimeMillis() - startTime) + "ms");

	}
}


最大堆

 

 

package cn.dream.sort;

import java.util.Arrays;

public class MaxHeapSortImpl implements IHeapSort {

	@Override
	public int getParent(int i) {
		return (int) (i - 1) / 2;
	}

	@Override
	public int getLeftChild(int i) {
		return 2 * i + 1;
	}

	@Override
	public int getRightChild(int i) {
		return 2 * i + 2;
	}

	@Override
	public int[] buildHeap(int[] a, int size) {
		for (int i = (size - 2) / 2; i >= 0; i--) {
			adjustHeap(a, i, size);
		}
		return a;
	}

	@Override
	public int[] adjustHeap(int[] a, int i, int size) {
		int largest = i;
		int temp = a[i];
		int left = getLeftChild(i);
		int right = getRightChild(i);

		if (left < size && a[left] > temp) {
			largest = left;
		}

		if (right < size && a[right] > a[largest]) {
			largest = right;
		}

		if (largest != i) {
			a[i] = a[largest];
			a[largest] = temp;
			adjustHeap(a, largest, size);
		}
		return a;
	}

	@Override
	public int[] sortHeap(int[] a, int size) {
		// buildHeap(a, size);
		int temp;
		for (int i = size - 1; i >= 0; i--) {
			temp = a[0];
			a[0] = a[i];
			a[i] = temp;
			adjustHeap(a, 0, i);
		}
		return a;
	}

	public static void main(String[] args) {
		int[] arr = { 53, 4, 24, 47, 41, 97, 13, 83, 12, 35, 11, 15, 41, 18,
				68, 49, 36, 52, 9, 45, 0, 38, 36, 82, 76, 22, 44, 35, 34, 81,
				94, 70, 88, 30, 42, 45, 55, 75, 93, 57, 74, 0, 77, 64, 93, 58,
				15, 62, 13, 49, 60, 21, 3, 66, 15, 74, 48, 96, 52, 56, 63, 73,
				85, 44, 39, 42, 98, 38, 17, 81, 7, 60, 86, 79, 63, 66, 17, 78,
				78, 90, 23, 92, 79, 21, 80, 71, 6, 70, 59, 25, 41, 11, 64, 60,
				62, 51, 93, 46, 18, 31 };

		long startTime = System.currentTimeMillis();

		IHeapSort heapSort = new MaxHeapSortImpl();

		System.out.println("测试最大堆的根节点是否最大值:");
		heapSort.buildHeap(arr, arr.length);
		System.out.println("root is:" + arr[0]);

		System.out.println("测试最大堆的顺序是否为倒序:");
		System.out.println(Arrays.toString(arr));
		
		System.out.println("排序:");
		heapSort.sortHeap(arr, arr.length);
		System.out.println(Arrays.toString(arr));

		System.out.println((System.currentTimeMillis() - startTime) + "ms");

	}

}

 

 

 

 

 

 

 

更多排序,,参考这位的http://blog.csdn.net/han_xiaoyang/article/details/12163251

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值