【知了堂学习笔记】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];
            }
        }
    }

}

 运行结果:

 

 

posted @ 2017-10-18 18:29  皮皮潇  阅读(257)  评论(0编辑  收藏  举报