算法之堆排序

Java code:

package com.cn.insertion;

public class HeadSort {
	public static void main(String[] args) {
		int[] a = new int[]{4, 1, 3, 2, 16, 9, 10, 14, 8, 21};
		HeadSort heapSort = new HeadSort();
		heapSort.headSort(a);
		for (int i = 0; i < a.length; i++) {
			System.out.println(a[i]);
		}
		
	}
	/**
	 * 这个是排序函数,因为大顶堆的根节点可以确定是最大的,所以每次交换
	 * 根节点到最后面,然后大顶堆的节点数目减一,后面的一定是排好序了的。
	 * 这个函数共进行O(n)趟,所以整个排序的时间复杂度为O(nlog(n)).
	 * @param a
	 */
	public void headSort(int[] a) {
		buildMaxHeap(a);
		int heapLength = a.length;
		for (int i = 0; i < a.length - 1; i++) {
			exchange(a, 1, heapLength);
			heapLength--;
			maxHeapify(a, 1, heapLength);
		}
		
		
	}
	/**
	 * 建立一个大顶堆,大顶堆满足父节点比两个孩子节点都大
	 * @param a
	 */
	public void buildMaxHeap(int[] a) {
		int heapLength = a.length;
		for (int i = a.length/2; i >= 1; i--) {
			maxHeapify(a, i, heapLength);
		}
	}
	//下面三个方法分别求出父节点,左孩子,右孩子
	public int parent(int i) {
		return i/2;
	}
	public int leftChild(int i) {
		return 2*i;
	}
	public int rigthChild(int i) {
		return 2*i + 1;
	}
	/**
	 * 三个参数a是要排序的数组,m是从那一个节点开始调整,n是我们要调整的堆的总长度。
	 * 每次找到父节点,左孩子,右孩子三个节点中最大的那一个,如果不是父节点最大,就
	 * 交换父节点与这个最大值得节点(可能是左孩子,也可能是右孩子),然后与父节点交
	 * 换了的节点的值变动了,所以在调用这个函数对以该节点为父节点的三堆在进行一次调
	 * 整。这样一趟调整的时间复杂度是O(log(n))。
	 * @param a
	 * @param m
	 * @param n
	 */
	public void maxHeapify(int[] a, int m, int n) {
		int l = leftChild(m);
		int r = rigthChild(m);
		int largest = m;
		if (l <= n && a[l - 1] > a[m - 1]) {
			largest = l;
		}
		if (r <= n && a[r - 1] > a[largest - 1]) {
			largest = r;
		}
		if (largest != m) {
			exchange(a, m, largest);
			maxHeapify(a, largest, n);
 		}
		
		
	}
	//对数组中的两个元素进行交换
	public void exchange(int[] a, int m, int n) {
		a[m - 1] = a[m - 1] + a[n - 1];
		a[n - 1] = a[m - 1] - a[n - 1];
		a[m - 1] = a[m - 1] - a[n - 1];
	}
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值