• 高级排序


    一、希尔排序(对插入排序进行优化)

         原理:1.选定一个增长量h,按h作为分组依据,对数据进行分组

                    2.对分好组的每一组进行插入排序

                    3.减少增长量,最少减为一,重复第二步操作

       增长量的确定:

         

    int h=1;
    while(h<数组长度/2){
    h=2h+1;
    }
    //循环结束后就是最大的h
    //h的减小规则
    h=h/2;

      

        public static void sort(Comparable[] a){
            //增长量h
            int h=1;
            //根据数组长度来确定增长量h的值
           while (h<a.length/2){
                h=2*h+1;
            }
           //写入排序
            while(h>=1){
                //排序
                //找到待插入元素
                 for(int i=h;i<a.length;i++){
                     //把待插入元素插入到有序数列中
                     for(int j=i;j>=h;j-=h){
                         //待插元素为a[j],与a[j-h]比较
                         if(greater(a[j-h],a[j])){
                             exch(a,j-h,j);
                         }else{
                             break;
                         }
                     }
                 }
                //h减少
                h=h/2;
            }
        }

    二、归并排序

             原理:1. 尽可能的一组数据拆分为相等的两份,并对每一个自组继续进行拆分,直到拆分后每个自组的元素个数为1;

                        2. 将两个自组合并成一个有序的大组

                        3.不断重复步骤2,直到成为一个大组

                      

    public class Merge {
        public static void main(String[] args) {
            //原数组
          int[] a={9,8,6,5,2,1};
            //归并所需要的复制数组
          int[] tem=new int[a.length];
          int lo=0;
          int hi=a.length-1;
          sort(a,lo,hi,tem);
          System.out.println(Arrays.toString(a));
        }
        /**
         *对数组a从lo到hi进行排序
         * @param a
         */
        public static void sort(int[] a,int lo,int hi,int[] tem){
            if(lo<hi){
                //将数组进行分组
                int mid=(lo+hi)/2;
                //分组之后对每一组进行排序
                sort(a,lo,mid,tem);
                sort(a,mid+1,hi,tem);
                //再把两个数组进行归并
                 merge(a,lo,hi,mid,tem);
            }
    
    
        }
        /**
         * 对数组,从lo到mid,mid+1到hi两个数组合并排序
         */
        public static void merge(int[] a,int lo,int hi,int mid,int[] tem){
            //此指针指向辅助数组
            int i=lo;
            //此指针指向前数组
            int p1=lo;
            //此指针指向后面的数组
            int p2=mid+1;
            //遍历,移动p1和p2,如果p1指针超过mid或者p2超过mid结束
              while(p1<=mid && p2<=hi){
                  if(a[p1]<a[p2]){
                      tem[i++]=a[p1++];//把a[p1]给辅助数组,并且指针后移
                  }else{
                      tem[i++]=a[p2++];
                  }
              }
            //如果p1指针指向的数组没遍历完,那么直接赋给tem
              while (p1<=mid){
                  tem[i++]=a[p1++];
              }
            //如果p2指针指向的数组没遍历完,那么直接赋给tem
            while (p2<=hi){
                tem[i++]=a[p2++];
            }
            //把assist数组拷贝到a数组中
            for (int index=lo;index<=hi;index++){
                    a[index]=tem[index];
            }
        }
    }

    三、快速排序

          原理:快速排序是对冒泡排序的改进;

                    1. 首先选定一个分界值,将数组分为两部分

                    2. 将大于等于分界值的数据放到右边,小于的放到左边

                    3. 对左边和右边分别进行2步骤

                    4. 重复上述步骤,通过递归对左右两部分进行排序,最后完成

                       

        把一个数组切分为两个数组的原理:

                1.找一个基准值(一般为第一个元素,6),用两个指针分别指向数组的头部和尾部+1的位置

                  

                 2.先从尾部向头部开始搜索一个比基准值小的元素,并停止,记录元素。

                 3.再从头部向尾部开始搜索一个比基准值小的元素,并停止,记录元素。

                 4.交换左右指针所指的值。

                 5.重复上述操作

    public class Partition{
        public static void main(String[] args) {
            //原数组
          int[] a={1,6,2,12,9,10};
          int lo=0;
          int hi=a.length-1;
          sort(a,lo,hi);
          System.out.println(Arrays.toString(a));
        }
        /**
         *对数组a从lo到hi进行排序
         * @param a
         */
        public static void sort(int[] a,int lo,int hi){
            if (lo<hi){
                //对数组a从lo到hi进行分组(左和右子组),返回分界索引
                int partition = partition(a, lo, hi);
                //对左子组进行排序
                sort(a,lo,partition-1);
                //对右子组进行排序
                sort(a,partition+1,hi);
            }
    
        }
        /**
         * 对数组,从lo到hi两个数组进行分组并返回分界索引
         */
        public static int partition(int[] a,int lo,int hi) {
            //分界值
            int key=a[lo];
            //头指针
            int left=lo;
            //尾指针的下一个位置
            int right=hi+1;
            while (true)
            {
                //先从右往左扫描,移动right,如果right所指的值小于key则停止
                while (a[--right]>key){
                    if(right==lo){
                        break;
                    }
                }
                //从左往右扫描,移动left,如果left所指的值大于key则停止
                while (a[++left]<key){
                    if (left==hi){
                        break;
                    }
                }
                //判断left>=right,则扫描完毕,结束循环,如果不是则交换元素
                if (left>=right){
                    break;
                }else {
                    exch(a,left,right);
                }
            }
            exch(a,lo,right);
            return right;
        }
    
        private static void exch(int[] a, int hi, int lo) {
            int temp = 0;
            temp =a[lo];
            a[lo]=a[hi];
            a[hi]=temp;
        }
    }

     四、排序的稳定性

          1.定义:假设数组a中右若干元素,其中A和B相等,在A在B的前面,在排完序之后任能保证A在B的前面,则稳定

           2.常见排序算法的稳定性

               稳定的:排序、插入、归并

               不稳定的:选择、希尔、快速

           

  • 相关阅读:
    简直喝血!H.265要被专利费活活玩死
    python异常处理
    开始好好总结所学东西了,马上校招了~~
    pip 安装管理失败解决
    去除空格
    自定义开关(不带有滑动,只具有点击切换开关功能)
    Android-ViewPagerIndicator框架使用——TabPageIndicator以及样式的修改
    Android详细的对话框AlertDialog.Builder使用方法
    Fragment+FragmentTabHost组件实现常见主页面(仿微信新浪)
    Activity生命周期
  • 原文地址:https://www.cnblogs.com/cqyp/p/12547247.html
Copyright © 2020-2023  润新知