java树结构应用之堆排序的原理以及实现

首先介绍下堆排序吧,说道堆排序就不得不说引发堆排序的一系列问题,就是如何从一堆无序的数中找出最大的数或者最小的数,亦或者找出其他大小的数,实际上就是对一堆数进行排序,能够让一堆无序的数按照大小顺序进行排列。

堆排序的原理其实就是应用了java数据结构中的二叉树结构,这里小编找到一个比较详细的博客,

https://www.cnblogs.com/web424/p/6911892.html

堆分为两类,为最大堆和最小堆。

最大堆:任何非叶子节点的值都大于他左右孩子节点的值;

最小堆:任何非叶子节点的值都小于他左右孩子节点的值;

下面描述下最大堆排序

首先找到最后一个非叶子节点,将他的值和左右孩子的值进行比较,如果左右孩子的值比他大,那么就互换值,就这样依次往上传直到最上方的节点最大,这时候输出这个节点的值并且将这个值移出树,再对剩下的数再一次就行排序,就这样依次移出值,直到这堆无序的数被从大到小排好为止。这样我们就得到了一个有序排列的数组,上文提到的问题也就迎刃而解了。排序分为两个阶段,1阶段是调整节点值使之成为最大堆,2阶段是移出树顶点的值,并把最后一个叶子节点的值赋给树顶点,在进行调整。最后就会得到一段排序好的数字了。

下面贴代码,首先是调整节点值的方法(1阶段)

public static void adjust(int[]a,int n,int k){
		//n为数组里有效数字个数
		int k1=2*k+1;
		int k2=2*k+2;
		
		//定义左右孩子的值
		int a1=Integer.MAX_VALUE;
		int a2=Integer.MAX_VALUE;
		//左孩子值
		if(k1<n){
			a1=a[k1];
		}
		//右孩子值
		if(k2<n){
			a2=a[k2];
		}
		if(a1<a2){
			int t=a[k];
			a[k]=a[k1];
			a[k1]=t;
			adjust(a,n,k1);
		}else{
			int t=a[k];
			a[k]=a[k2];
			a[k2]=t;
			adjust(a,n,k2);
		}
	}

这里需要注意的是,在子节点和父节点的值互换了之后,可能会对这里的子节点下面的子节点造成影响,使最大堆不成立,所以需要再次调整。

下面是建立堆并且输出堆的方法(2阶段):

public void sort(int[]a){
		//建立初始堆,a.length-1/2为最后一个非叶子节点的位置
		for(int i=(a.length-1)/2;i>=0;i--){
			//边输出顶堆边调整
			adjust(a,a.length,i);
		}
		int n=a.length;
		while(n>0){
			System.out.print(a[0]+" ");
			a[0]=a[n-1];
			n--;
			adjust(a,n,0);
		}
	    System.out.println();
	}

这样最大堆排序就差不多OK了,总的来说,理解其实挺简单的,但是实际操作起来还是不那么简单的,多思考就行了。

猜你喜欢

转载自blog.csdn.net/qq_29694477/article/details/81950610