【知了堂学习笔记】java 编写几种常见排序算法3
排序的分类:
1.希尔排序
希尔排序是快速插入排序的改进版,希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止
基本思路:先取一个小于n的整数d1作为第一个增量,把文件的全部记录分组。所有距离为d1的倍数的记录放在同一个组中。先在各组内进行直接插入排序;然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量 =1( < …<d2<d1),即所有记录放在同一组中进行直接插入排序为止,一般是选取d1为数组的一半,d2为d1的一半以此类推..
具体代码:
package Sort; public class Shell_sort { public static void main(String[] args) { // TODO Auto-generated method stub int[] a = {78,68,48,39,95,48,94,73}; //希尔排序 int d=a.length; while(d>1) { d=d/2; for(int x=0;x<d;x++) {//以d为公差分组,分成d个数组,每个数组为{a[i+d],a[i+2d],a[i+3d]....} for(int i=x+d;i<a.length;i=i+d) {//按直接插入排序将这些数组排序(具体方法查看我的直接插入排序http://www.cnblogs.com/pipixiao/p/7674142.html) int temp=a[i]; int j; for(j=i-d;j>=0&&a[j]>temp;j=j-d) { a[j+d]=a[j]; } a[j+d]=temp; } } } System.out.println("排序之后:"); for(int i=0;i<a.length;i++) { System.out.print(a[i]+" "); } } }
运行结果:
2.堆排序
大根堆排序,小根堆排序。
大根堆排序:先构建二叉树(构建的二叉树必须满足父节点必须大于其左右子节点,数组中第一个数字为a【0】其左右子节点的应为a【1】,a【2】,以脚标定义既是父节点为a【i】,其左右子节点分别为a【2i+1】,a【2i+2】),再将二叉树中第一个数获取放入另外一个空数组中,剩下的数重新形成一个新的数组,再重新建堆,重复上述步骤,直到原数组中数字被取完,得到的新数组,既是一个由大到小排序完成的数组
由此二叉树可知2是5,6的父节点,将2,5,6三个位置的数比较大小,得到最大的数与2位置的交换,当得到的数就是2本身,不做交换,(1,3,4),(0,1,2)位置的数也应该做同样的步骤,这样最终0位置获得的数既是最大的数,然后将得到的数组中a【0】拿出,后面的数构建新数组,重新再构建树。重复上述步骤
注意:这里可以看出构建数循环的次数为3次即:for(int i=(a.lenght-1)/2-1,i>=0,i--);但是当出现下面这种情况时很显然这个条件不满足,下面循环的次数为4次,我们可以不改变上述循环的原理上面加一点既:for(int i=(a.lenght-1)/2-1+(a.lenght-1)%2;i>=0;i--)其实对比不难看出当数组的长度为偶数的时候,得到的二叉树最后悔单出来一个位置,这里面比较的条件就会发生变化,而(a.lenght-1)%2可以得到长度为偶数则加一次循环,为奇数时不变。
构建的数是这种情况的时候(3,7)位置的数比较的时候只有两个数比较,所以这里出现了一个不同,就应该加一个判断条件(本次比较是否存在a【2i+2】这一项,如果不存在则比较的数只有a【i】与a【2i+1】)
具体代码:
package Sort; import java.util.Arrays; public class HeapSort { public static void main(String[] args) { // TODO Auto-generated method stub int[] arr = {78,68,48,39,95,48,94,73}; int[] a = new int[8]; for(int i=0;i<a.length;i++){ heap(arr); a[i]=arr[0];//将当前数组第一个数获取给数组a arr=Arrays.copyOfRange(arr,1,arr.length);//截取取arr数组的第一个数后面的所有数,重新给arr } for (int m = 0; m < a.length; m++) {//遍历输出数组a,数组a既是排序完成后的数组 System.out.print(a[m]+" "); } } public static void heap(int[] arr){//创建堆 int temp=0; for(int j=(arr.length-1)/2-1+(arr.length-1)%2;j>=0;j--){//获取每次创建堆的循环条件 if(2*j+2<=arr.length-1){//判断当前a[2*j+2]是否存在,存在则执行a[j]、a[2*j+1]、a[2*j+2]比较,不存在则执行a[j]、a[2*j+1]比较 temp=arr[j]>arr[2*j+1]?(arr[j]>arr[2*j+2]?j:2*j+2):(arr[2*j+1]>arr[2*j+2]?2*j+1:2*j+2);//比较获得最大数的脚标 }else{ temp=arr[j]>arr[2*j+1]?j:2*j+1; } if(arr[j]==arr[temp]){//如果最大的数就是a[j]本身则退出进行下一次比较 continue; }else{//最大数不是a[j]则最大数与a[j]交换位置 arr[j]=arr[j]^arr[temp]; arr[temp]=arr[j]^arr[temp]; arr[j]=arr[j]^arr[temp]; } } } }
运行结果: