堆排序

木子津發表於2020-11-21

堆排序過程:(這裡選用大頂堆)

     一個完整的堆排序需要經過反覆的兩個步驟:構造堆結構和堆排序輸出。

一、構造堆結構

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");

	}

}

結果如下:


相關文章