堆排序

堆排序过程:(这里选用大顶堆)

     一个完整的堆排序需要经过反复的两个步骤:构造堆结构和堆排序输出。

一、构造堆结构

1)将原始的数据,按层遍历,依次放置到一个完全二叉树的各个节点中;

2)对这个完全二叉树进行编号,从根开始,按层遍历,依次编号为1、2、3、,...,n;

3)从编号为┗n/2┛的结点开始,进行“左--根--右”的父子结点值比较。大数放在父结点,小数放在子结点。

4)接着,从编号为┗n/2┛-1的结点开始,也是“左--根--右”,父大子小。

5)直到编号为1的结点,继续“左--根--右”,父大子小。

二、堆排序输出

   将大顶堆中的根结点与最后的叶子结点进行交换,然后对序列中的前n-1记录进行筛选,重新把完全二叉树调整为一个“大顶堆”,如此反复,直到排序结束。

   a)对于大根堆,我们采用的是从小到大输出,因此将其放到数组的末尾,如图a,结点97与结点38交换,

   b)将结点38换到根结点的位置后,要从新构造堆,即使它保持大根堆的结结构,此时结点97已不在堆中。如图b

   c)重复上述过程,取此时堆结构的根节点(最大值)进行交换,放在数组后面,此时结点77与结点38交换。如图c

   d)然后重复将剩余的数据构造堆结构,取根结点与最后一个结点交换,将得到图d所示结果。

   e)再进一步执行堆排序输出,编号1与编号3互换,得到图e结果。

   f)对最后的两个数据进行处理,得到最终结果。

代码如下:

package cn.whut.sort;

public class HeapSort2 {
	static final int SIZE=10;
	
	/**
	 * 堆排序
	 * @param a,数组a
	 * @param n,个数为n
	 */
	static void heapSort(int a[],int n)					
	{
	    int i,j,h,k;
	    int t;

	    for(i=n/2-1;i>=0;i--)    				//将a[0,n-1]建成大根堆
		{
			while(2*i+1<n) 					//第i个结点有右子树 
			{
				j=2*i+1 ;
				if((j+1)<n)
				{            
				    if(a[j]<a[j+1])			//右左子树小于右子树,则需要比较右子树
				        j++; 				//序号增加1,指向右子树 
				}
				if(a[i]<a[j])					//比较i与j为序号的数据
				{            
				    t=a[i];  				//交换数据 
					a[i]=a[j];
					a[j]=t;            
					i=j ;					//堆被破坏,需要重新调整
				}
				else 					//比较左右子结点均大则堆未破坏,不再需要调整
				{
					break;
				}
			}
		}
	    
		//输出构成的堆
		System.out.print("原数据构成的堆:");		
		for(h=0;h<n;h++)
		{
			System.out.print(" "+a[h]);				//输出
		}
		System.out.print("\n");

	    for(i=n-1;i>0;i--)
	    {
	        t=a[0];							//与第i个记录交换
	        a[0] =a[i];
	        a[i] =t;
			k=0;
			while(2*k+1<i) 					//第i个结点有右子树 
			{
				j=2*k+1 ;
				if((j+1)<i)
				{            
				    if(a[j]<a[j+1])			//右左子树小于右子树,则需要比较右子树
					{
				        j++; 				//序号增加1,指向右子树 
					}
				}
				if(a[k]<a[j])				//比较i与j为序号的数据
				{            
				    t=a[k];  				//交换数据 
					a[k]=a[j];
					a[j]=t;            
					k=j ;					//堆被破坏,需要重新调整
				}
				else 					//比较左右子结点均大则堆未破坏,不再需要调整
				{
					break;
				}
			}

			System.out.print("第"+(n-i)+"步排序结果:");		//输出每步排序的结果
			for(h=0;h<n;h++)
			{
				System.out.print(" "+a[h]);			//输出
			}
			System.out.print("\n");
	    }  
	}
	
	public static void main(String[] args)
	{
		int[] shuzu=new int[SIZE];
		int i;
		
		for(i=0;i<SIZE;i++)
		{
			shuzu[i]=(int)(100+Math.random()*(100+1));			//初始化数组
		}
		
		System.out.print("排序前的数组为:\n");				//输出排序前的数组
		for(i=0;i<SIZE;i++)
		{
			System.out.print(shuzu[i]+" ");
		}
		System.out.print("\n");
		
		heapSort(shuzu,SIZE);					//排序操作
		
		System.out.print("排序后的数组为:\n");
		for(i=0;i<SIZE;i++)
		{
			System.out.print(shuzu[i]+" ");					//输出排序后的数组
		}
		System.out.print("\n");

	}

}

结果如下:

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sanqima

一键三连,多多益善

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值