堆排序 java实现

难得一个周五,没有什么事情,我于是用java 写了一个堆排序算法,忙活了很长时间,觉得自己写的不错的时候,问问 同事——可,可很easy写了出来,我仔细学了学他的思路,不错,比我的好,我特别留下的代码,今后学习使用:

 

先介绍一下堆排序:

 

1.堆

  堆实际上是一棵完全二叉树,其任何一非叶节点满足性质:

  Key[i]<=key[2i+1]&&Key[i]<=key[2i+2]或者Key[i]>=Key[2i+1]&&key>=key[2i+2]

  即任何一非叶节点的关键字不大于或者不小于其左右孩子节点的关键字。

  堆分为大顶堆和小顶堆,满足Key[i]>=Key[2i+1]&&key>=key[2i+2]称为大顶堆,满足 Key[i]<=key[2i+1]&&Key[i]<=key[2i+2]称为小顶堆。由上述性质可知大顶堆的堆顶的关键字肯定是所有关键字中最大的,小顶堆的堆顶的关键字是所有关键字中最小的。

2.堆排序的思想

   利用大顶堆(小顶堆)堆顶记录的是最大关键字(最小关键字)这一特性,使得每次从无序中选择最大记录(最小记录)变得简单。

    其基本思想为(大顶堆):

    1)将初始待排序关键字序列(R1,R2....Rn)构建成大顶堆,此堆为初始的无序区;

    2)将堆顶元素R[1]与最后一个元素R[n]交换,此时得到新的无序区(R1,R2,......Rn-1)和新的有序区(Rn),且满足R[1,2...n-1]<=R[n]; 

    3)由于交换后新的堆顶R[1]可能违反堆的性质,因此需要对当前无序区(R1,R2,......Rn-1)调整为新堆,然后再次将R[1]与无序区最后一个元素交换,得到新的无序区(R1,R2....Rn-2)和新的有序区(Rn-1,Rn)。不断重复此过程直到有序区的元素个数为n-1,则整个排序过程完成。

    操作过程如下:

     1)初始化堆:将R[1..n]构造为堆;

     2)将当前无序区的堆顶元素R[1]同该区间的最后一个记录交换,然后将新的无序区调整为新的堆。

    因此对于堆排序,最重要的两个操作就是构造初始堆和调整堆,其实构造初始堆事实上也是调整堆的过程,只不过构造初始堆是对所有的非叶节点都进行调整。

 

代码如下:

package array;

public class heapSort {
	public enum location {

		Right, Left, Root;
	}

	public location judgeLarge(int[] aa, int index, int length) {
		// both of the right node and left node do not exist;
		if (2 * index + 1 > length - 1) {
			return location.Root;
		}
		if (2 * index + 1 == length - 1) {
			if (aa[index] > aa[2 * index + 1])
				return location.Root;
			else
				return location.Left;
		}
		if (aa[2 * index + 2] >= aa[2 * index + 1]) {
			return aa[2 * index + 2] > aa[index] ? location.Right
					: location.Root;
		}
		if (aa[2 * index + 1] >= aa[2 * index + 2]) {
			return aa[2 * index + 1] > aa[index] ? location.Left
					: location.Root;
		}
		return null;

	}

	public void buildhead(int[] aa, int length) {

		int lastnotleft = (length - 1 - 1) / 2;
		for (int i = lastnotleft; i >= 0; i--) {

			location postion = judgeLarge(aa, i, length);
			judgeandexchange(aa, postion, i, length);

		}

	}

	public void judgeandexchange(int[] aa, location postion, int index,
			int length) {
		if (postion == location.Left) {
			arrayexchange.exchange(aa, index, 2 * index + 1);
			location newpostion = judgeLarge(aa, 2 * index + 1, length);
			if (newpostion != location.Root || newpostion != null)
				judgeandexchange(aa, newpostion, 2 * index + 1, length);
		}
		if (postion == location.Right) {
			arrayexchange.exchange(aa, index, 2 * index + 2);
			location newpostion = judgeLarge(aa, 2 * index + 2, length);
			if (newpostion != location.Root || newpostion != null)
				judgeandexchange(aa, newpostion, 2 * index + 2, length);
		}

	}

	public void sort(int[] aa) {

		for (int i = aa.length; i > 0;) {
			arrayexchange.exchange(aa, 0, i - 1);
			buildhead(aa, --i);
		}
	}

	public static void main(String[] args) {
		heapSort hs = new heapSort();

		int[] a = { 16, 7, 3, 20, 17, 8 };
		hs.buildhead(a, a.length);
		for (int k : a) {
			System.out.print(" " + k);
		}
		System.out.println();
		hs.sort(a);
		for (int k : a) {
			System.out.print(" " + k);
		}
	}

}

 这是我写的,感觉写的好复杂啊,自己的思路台混乱了

 

下面是可写的,简单,明了

 

package array;

public class sort {

	public static void sort(int[] a) {
		for (int i = a.length / 2 - 1; i >= 0; i--) {
			int left, right;
			left = i * 2 + 1;
			right = i * 2 + 2;
			if (right < a.length) {
				left = (a[left] <= a[right]) ? left : right;
			}
			if (a[left] < a[i]) {
				change(a, left, i);
			}

		}

	}

	public static void resort(int[] a) {
		int len = a.length;
		while (len > 1) {
			change(a, 0, len - 1);
			len--;
			for (int i = 0; i < len; i++) {
				int left = i * 2 + 1, right = i * 2 + 2;
				if (left >= len)
					break;
				if (right < len) {
					left = (a[left] <= a[right]) ? left : right;
				}
				if (a[left] < a[i])
					change(a, i, left);
			}

		}

	}

	public static void change(int a[], int i, int j) {
		int temp = a[i];
		a[i] = a[j];
		a[j] = temp;
	}

	public static void main(String args[]) {
		int a[] = { 16,7,3,20,17,8 };
		sort(a);
		resort(a);
		print(a);
	}

	public static void print(int a[]) {
		System.out.println();
		for (int i : a) {
			System.out.print(i + " ");
		}
	}

}

 

看来java还是有很大的差距阿!还需要努力啊!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值