排序&&堆排序
2018-02-26 10:33
190 查看
package Sort; import java.util.Arrays; /** * 堆排序 *1,堆排序也是选择排序的一种,根据堆的特性,每次把最大或最小值(本次以最大值为例) *拿出来,按序排列; 2,堆排序是对普通选择排序的一种优化:如果是一个稳定堆,每次在选择最大值时, 只用沿着二叉树其中一个分叉去交换即可,其他分叉符合堆得特性(因是排好的稳定堆), 可以看作是稳定的,不用重排交换,省去了绝大多数的比较交换步骤,数组的数越多,分 支越多,该算法的优势就越明显; 3,第一步,将数组初始化为稳定堆,稳定堆的特性:二叉树之父节点总比其左右孩子节点大! 初始化稳定堆有很多方法,可以从堆顶向堆底方向初始化,也可以从堆底向堆顶方向排列初 始化,也可以通过小三角递归调等完成初始化,本例为理解方便,选用从堆底向堆顶方向初始 化,即,每次从小三角里找到最大值放在父节点,从最后一个小三角向前循环,第一遍,找到 所有数的最大值,第二遍循环找到次最大值放在第二层节点上,依次类推,完成稳定堆得初始化; 4,初始化完稳定堆之后,将选出的最大值与最后一个数字交换放在数组的最后固定下来 (以后循环不再用到此数字),此时除了顶部三角不稳定,下面都是稳定的,根据稳定堆 得特性(父节点总是大于其左右孩子节点),从顶部往底部寻找交换,只沿着变动的那个 分叉交换下去(只用单线一次循环即可),其他分叉不用动,交换完毕后,次最大数又被移到 顶部,此时的堆仍然是一个稳定堆,再将顶部的最大值交换的数组的后面固定下来,重复这个 步骤,依次类推,即可完成; 排序趟数: 1,初始化堆所用趟数:不确定,最大趟数是二叉树的层数,最小一趟 2,初始化堆后所用趟数:length-2次 排序原理: 稳定堆特性,二叉树排序,具体见上述排序思想 * */ public class HeapSort { static int[] a; public HeapSort() { a=new int[] {8,19,2,3,100,99,1000,888,-1,0}; // a=new int[] {6,5,3,1,8,7,2,4}; } public HeapSort(int[] a) { this.a=a; } //堆排序 public static void heap_Sort(int[] array) { int length=array.length; inteHeap(array, length);//初始化稳定堆 System.out.println("初始化稳定堆"+Arrays.toString(array)); switchData(array, 0, length-1);//交换第一个元素和本轮最后一个元素 //二叉排序 for(int length2=length-1; length2>1; length2--) {//循环length-2次 int index=0; while(2*index+1<length2) {//只要有左孩子节点就能产生交换,进入循环 if(2*index+2<length2) {//左右孩子都有 int max=index; //默认是父节点的下标 if(array[max]<array[2*index+1]) { max=2*index+1;//返回左孩子的下标 } if(array[max]<array[2*index+2]) { max=2*index+2;//返回右孩子的下标 } if(max!=index) { switchData(array, index, max); index=max; }else { break;//max=index;表示节点最大,下面的堆都是稳定的,不用继续循环 } } if(2*index+1<length2 &&2*index+2>=length2)//只有左孩子没有右孩子 if(array[index]<array[2*index+1]) { switchData(array, index, 2*index+1); }else { break;//2*index+1==index表示节点最大,下面的对是最稳定的,不用继续循环 } } put(); System.out.println(); switchData(array, 0, length2-1); put(); System.out.println(); } } //初始化堆 所有的根都大于他的孩子 public static void inteHeap(int[] array,int length) { int high=length-1;//最大下标 boolean isChange=false; //K的初始值就是最大的一个非终端节点 for(int k=(high-1)/2;k>=0;k--) { //找到最后一个父节点 int left=2*k+1; //左孩子的下标 int right=left+1;//右孩子的下标 //判断是否有节点 if(left<=high) { int max=left; if(right<=high) { if(array[left]<array[right]) { max=right; //返回左孩子或右孩子中值最大的下标 } } //将最大值根父节发交换 if(array[max]>array[k]) { isChange=true; switchData(array,max,k); } } } if(isChange) {//如果一次就能完成稳定堆的初始化,则不需要递归调用,以达到优化算法 inteHeap(array, length); System.out.println("递归"+Arrays.toString(array)); } } //交换数组中俩个数的方法因为要多次用到,所以封装成一个方法 public static void switchData(int[] array,int index1,int index2) { array[index1]^=array[index2]; array[index2]^=array[index1]; array[index1]^=array[index2]; } //遍历 public static void put() { for (int i : a) { System.out.print(i+"\t"); } } public static void main(String[] args) { HeapSort hp=new HeapSort(); hp.heap_Sort(a); hp.put(); } }
相关文章推荐
- 常用算法(2)--选择排序&堆排序
- Data Structure & Java: 堆、堆排序与PriorityQueue
- 【数据结构&&算法系列】堆排序简单介绍及其实现
- POJ 2388 Who's in the Middle(堆排序)
- hash_map<string,int>的堆排序实现
- 选择排序:直接选择排序&堆排序
- 排序&&单链表反转
- 排序&约瑟夫环&单链表逆置&字符串四则运算
- Data Structure & Java: 堆、堆排序与PriorityQueue
- Seoul 2007 / UVa 1398 Meteor (排序&线性扫描)
- 二叉堆 & 堆排序
- 堆 && 堆排序
- RandomAccessFile&IO流&排序&方法论
- datatable的自定义配置-输出结果&排序&跳转指定页码
- Python 面试题 - 堆排序 & 演算过程
- Oracle基本语法&&函数&&子查询&&分页查询&&排序&&集合操作&&高级分组函数
- 结构体-排序&nbsp;sort()&nbsp;swap()
- 九度:1014<排序>
- <菜鸟学算法-A排序(分治的思想:堆排序)>
- Java算法分析2—————几种排序&汉诺塔算法