zoukankan      html  css  js  c++  java
  • 【知了堂学习笔记】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];
                }
            }
        }
    
    }

     运行结果:

  • 相关阅读:
    python面向对象
    Python基本数据类型
    小刘同学的第一百四十四篇博文
    小刘同学的第一百四十三篇日记
    小刘同学的第一百四十二篇日记
    小刘同学的第一百四十一篇日记
    小刘同学的第一百四十篇日记
    小刘同学的第一百三十九篇博文
    小刘同学的第一百三十八篇日记
    小刘同学的第一百三十七篇日记
  • 原文地址:https://www.cnblogs.com/pipixiao/p/7687930.html
Copyright © 2011-2022 走看看