常见算法之排序(进阶部分)_堆排序_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万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章