常見算法之排序(進階部分)_堆排序_04

package junior.DAY_01;

public class Code_01_Sort 
{
	public static void main(String[] args) 
	{
		//初始化數組
		int len = (int)(Math.random()*20);//隨機生成20以內的數組長度
		int[] arr = new int[len];
		for(int i = 0; i < len; i++)//在數組內隨機生成1000內的值
		{
			arr[i] = (int)(Math.random()*1000) ;
		}
		for(int i = 0; i < len; i++)//格式化輸出數組
			System.out.printf("%02d:%-4d\n",i,arr[i]);
		
		heapSort(arr);

		for(int i = 0; i < len; i++)//格式化輸出數組
			System.out.printf("%02d:%-+4d\n",i,arr[i]);

	}
	
	
	
	public static void heapSort(int[] arr)
	{//概念
		//完全二叉樹:滿二叉樹或者滿二叉樹的過程樹
		//用數組表示完全二叉樹:
			//索引i的左節點索引爲:i*2+1  i*2+2  如果越界,則表示無該節點
			//索引i的父節點索引爲:(i-1)/2   
		
		//大根堆:整棵樹的最大值就是根節點,每顆子樹的最大值就是該子樹的頭結點
		//將數組調成最大堆的方式:數組中的每個元素都與父節點比較,如果比父節點大,則和父節點交換位置,
			//交換位置後還 應繼續與父節點比較,直至小於父節點爲止
		
		//將最大堆調成有序:將根節點與最後一個節點交換,這樣就把最大值換到了最後,並保持最大值的位置不變
			//將堆的範圍-1(不理會最大值)。
			//然後將根節點與較大的左右孩子節點作比較,如果孩子節點比較大,則交換位置;
			//交換位置後繼續與孩子節點比較,直至比孩子節點大
			//循環上面的步驟
		if(arr == null || arr.length < 2)
			return;
		
		for(int i = 0; i < arr.length; i++)//將數組調成最大堆
			heapInsert(arr,i);
		
		int heapSize = arr.length;
		int tmp = arr[0];//將最大堆的根節點和未排序堆的最後一個節點交換位置
		arr[0] = arr[heapSize-1];
		arr[heapSize-1] = tmp;
		heapSize--;//將堆最後一個節點劃入已排序部分
		
		while(heapSize > 0)//只要未排序部分還有元素,則繼續循環
		{
			heapify(arr,0,heapSize);//重新將未排序部分調整成最大堆
			tmp = arr[0];//將最大堆的根節點和未排序堆的最後一個節點交換位置
			arr[0] = arr[heapSize-1];
			arr[heapSize-1] = tmp;
			heapSize--;//將堆最後一個節點劃入已排序部分
		}
	}
	
	public static void heapInsert(int[] arr, int index)
	{//將數組調成最大堆的方式:數組中的每個元素都與父節點比較,如果比父節點大,則和父節點交換位置,
		//交換位置後還 應繼續與父節點比較,直至小於父節點爲止
		//往上走
		while(arr[index] > arr[(index-1)/2])
		{
			int tmp = arr[index];
			arr[index] = arr[(index-1)/2];
			arr[(index-1)/2] = tmp;
			index = (index-1)/2;
		}
	}
	
	public static void heapify(int[] arr, int index, int size)
	{//將未排序部分調成最大堆 index表示開始調整位置  size表示堆的大小
		//往下走
		int left = index*2 + 1;
		while(left < size)//保證左孩子節點不越界
		{
			
				
			int largest = 0;//
			if(left+1 < size)//找出左右孩子節點比較大的節點
			{
				if(arr[left] > arr[left+1])
					largest = left;
				else
					largest = left+1;
			}
			else
				largest = left;
			if(arr[largest] < arr[index])//把較大的孩子節點與父節點比較
			{//如果沒能比父節點大,則停止
				largest = index;
				break;
			}
			else//如果較大的孩子節點比父節點大,則與父節點交換位置
			{
				int tmp = arr[largest];
				arr[largest] = arr[index];
				arr[index] = tmp;
				index = largest;//交換之後再接着與孩子節點比較
				left = index*2+1;
			}
		}
	}
}

發佈了52 篇原創文章 · 獲贊 47 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章