A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

昨天在论坛看见有人在问希尔排序,我想着前两天用过快速排序和冒泡  选择等做过测试 顺便把这个希尔排序也看一下算了希尔排序时对插入排序的优化 如果现在要升序排列
插入排序就是  将一个无序的数组  从第二个位置开始和前面的位置比较  如果比前面的数小  就将前面的数后移  一直这样下去 知道到了0下标 或者当前数比前面的数大   就将当前下标的位置填入这个数
        下标 0 1 2 3 4 5 6
做个例子 3 4 1 2 5 8 6
第一次 4和3 比较     大于  就不变化  现在3 4  已经是一个排好序的数组了
第二次 1和4  发现1<4    4后移  变成3 _ 4  中间是空出来的位置 然后以1和3比较 1<3  数组变成 _ 3 4  到达0下标 填入1
变成 1 3 4  
后面依次下去   目的就是保证每次都去插入一个数  这个被插入的数组里面都要是排好序的

希尔排序  就是对插入排序的优化  他是将数组分组   ,用增量(d   一般都是arr.length/2)来分组  这里d=7/2=3的话  上面那个数组
第一次 就是   下标  0 3 6               1 4  2 5
·  3 2 6     为一组4 5   为一组1 8
    这样对两组分别 插入排序
  第一组就是 2 3 6
  第二组就是  4 5
  第三组就是  1 8
  这样第一次排序的结果 2 4 1 3 5 8 6         
这时候d/=2   d=1      如果d!=1  继续上态依次下去 分组 插入排序
当d=1时就是普通的插入排序  只不过这的时候  因为前面分插入排序过  很多都是排好序的(排序好了 只要比一次)  所以这样最后一次比较就很少比较了      
  1. package com.liubo.test;

  2. import java.io.IOException;
  3. import java.util.Arrays;
  4. public class SortDemo02 {
  5.      public static void main(String[] args) throws InterruptedException, IOException {
  6.           int [] arr1=new int[10000];
  7.           int [] arr2=new int[10000];
  8.           int [] arr3=new int[10000];
  9.           int [] arr4=new int[10000];
  10.           int [] arr5=new int[10000];
  11.           int [] arr6=new int[10000];
  12.          
  13.           //随机生成10000个数据
  14.           for(int i=0;i<10000;i++){     
  15.                arr1[i]=(int) (Math.random()*1000);
  16.                arr2[i]=arr1[i];
  17.                arr3[i]=arr1[i];
  18.                arr4[i]=arr1[i];
  19.                arr5[i]=arr1[i];
  20.                arr6[i]=arr1[i];
  21.           }     
  22.           System.out.println("测试数据个数:"+arr1.length);
  23.          
  24.           long start=System.currentTimeMillis();
  25.           //自带排序
  26.           Arrays.sort(arr1);     //据说这个 有两种排序 基本数据类型用快递排序  饮用对象用的是堆排序
  27.           long end=System.currentTimeMillis();
  28.           System.out.println("Arrays.Sort  用时:"+(end-start));
  29.          
  30.           start=System.currentTimeMillis();
  31.           //冒泡排序
  32.           bubbleSort(arr2);
  33.           end=System.currentTimeMillis();
  34.           System.out.println("bubbleSort  用时:"+(end-start));
  35.          
  36.           //选择排序
  37.           start=System.currentTimeMillis();
  38.           selectSort(arr3);
  39.           end=System.currentTimeMillis();
  40.           System.out.println("selectSort  用时:"+(end-start));
  41.          
  42.           start=System.currentTimeMillis();
  43.           //插入排序
  44.           insertSort(arr4);
  45.           end=System.currentTimeMillis();
  46.           System.out.println("insertSort  用时:"+(end-start));
  47.          
  48.          
  49.           start=System.currentTimeMillis();
  50.           //希尔排序
  51.           myShellSort(arr5);
  52.           end=System.currentTimeMillis();
  53.           System.out.println("shellSort  用时:"+(end-start));
  54.          
  55.          
  56.           //快速排序    分治法
  57.           start=System.currentTimeMillis();
  58.           fastSort(arr6);
  59.           end=System.currentTimeMillis();
  60.           System.out.println("fastSort  用时:"+(end-start));
  61.      }
  62.           /*
  63.           * 冒泡排序  从最末尾的数开始来和前一个比较  每次将最小的浮到最上面
  64.           * */
  65.      private static void bubbleSort(int[] arr) {
  66.           boolean flag=true;   //用来判断  如果一次冒泡下来 没变化 就说么已经排序好了 后面就不用排序了
  67.           for(int i=0;flag&&i<arr.length-1;i++){
  68.                flag=false;
  69.                for(int j=arr.length-1;j>i;j--){
  70.                     if(arr[j]<arr[j-1]){
  71.                          swap(arr,j,j-1);
  72.                          //交换了说明变化了
  73.                          flag=true;
  74.                     }
  75.                }
  76.           }
  77.           //System.out.println(Arrays.toString(arr));;
  78.      }
  79.      
  80.      /*
  81.      * 每次遍历都找出最小的
  82.      * 和被遍历的最前面的换位置  这样每次都将最小的放在前面了
  83.      * */
  84.      private static void selectSort(int[] arr) {
  85.           int index=0;    //默认最小的在0
  86.           for(int i=0;i<arr.length-1;i++){
  87.                index=i;  //因为每次选择排序后   最小的都是剩下的最前面的那个
  88.                for(int j=i+1;j<arr.length;j++){
  89.                     if(arr[j]<arr[index]){
  90.                          index=j;
  91.                     }
  92.                }
  93.                if(index!=i)
  94.                swap(arr,index,i);
  95.           }
  96.           //System.out.println(Arrays.toString(arr));
  97.      }
  98.      
  99.      //插入排序
  100.      private static void insertSort(int[] arr) {
  101.           int index=0;   //被比较的位置
  102.           int key=0;// 去比较的数的值
  103.           for(int i=1;i<arr.length;i++){  //从第2个开始  与前面的比较  遇到第一个比他小的数 停留在那个数去的前一个位置
  104.                index=i-1;
  105.                key=arr[i];
  106.                //循环
  107.                while(index>=0 && key<arr[index]){
  108.                     //前面大的数 后后移一位
  109.                     arr[index+1]=arr[index];
  110.                     index--;   //在和前面的比较
  111.                }
  112.                //当遇到比自己晓得或者在最前面的时候
  113.                arr[index+1]=key;   //key的位置赵大鹏
  114.           }
  115.      //     System.out.println(Arrays.toString(arr));
  116.      }

  117.      //希尔排序
  118.      private static void myShellSort(int[] arr) {
  119.           int key=0;    //某个位置的数  要去和前面的数比较的
  120.           int j=0;
  121.           for(int d=arr.length/2 ; d>0 ;d/=2){
  122.                //将这些坐标的数 3 0是一对   4 1  5 2  类推   就是当前位置  当前位置-d
  123.                
  124.                for(int i=d;i<arr.length;i++){
  125.                     
  126.                     key=arr[i];   //拿出来   每次组里面的最后一个数
  127.                     //System.out.println(key);
  128.                     //在每组中插入排序
  129.                     for(j=i; j>=d;j-=d){
  130.                          //开始循环
  131.                               if(key < arr[j-d]){   //如果小于   就将前面大的数 移动后面那个空位置
  132.                                    arr[j]=arr[j-d];   
  133.                               }
  134.                               else{
  135.                                    break;
  136.                               }
  137.                     }
  138.                     arr[j]=key;
  139.                }
  140.           }
  141.           // System.out.println(Arrays.toString(arr));
  142.      }

  143.      /*
  144.      * 分治法 先去一个数  将数组中小于他的数放在他的左边   大于他的数放在他的右边    从右边找比他小的j      左边找比他大的i   j==i exit  
  145.      * 挖坑  填数    在依次对左边和右边这样
  146.      *
  147.      * */
  148.      private static void fastSort(int[] arr) {
  149.           int l=0,r=arr.length-1;
  150.           fast_sort(arr,l,r);
  151.           //System.out.println(Arrays.toString(arr));
  152.      }
  153.      private static void fast_sort(int[] arr, int l, int r) {
  154.           int x=arr[l];   //每次将进来的这一段数组 的最前的数为标准 晓得填到他的左边  大的填到他的右边
  155.           int i=r;
  156.           int j=l;
  157.           if(l<r){
  158.                while(j<i){
  159.                     //右边大的话就一直遍历下去  知道找到第一个小的
  160.                     for(;j<i&&arr[i]>=x;i--);
  161.                     //小的听到最前面的位置
  162.                     if(j<i)
  163.                     arr[j++]=arr[i];   //这时候i的位置空了
  164.                     
  165.                     //遍历左边的
  166.                     for(;j<i&&arr[j]<x;j++);
  167.                     //左边的移到右边空的位置
  168.                     if(j<i)
  169.                     arr[i--]=arr[j];
  170.                }
  171.                //最后i==j的时候
  172.                arr[i]=x;
  173.                //此时X为中间分为两段 分别递归
  174.                if(l<i-1)
  175.                fast_sort(arr,l,i-1);
  176.                if(r>i+1)
  177.                fast_sort(arr,i+1,r);
  178.           }
  179.      }

  180.      //swap的
  181.      public static void swap(int[] arr, int j,int k){
  182.           arr[j]=arr[j]^arr[k];                    //     5^3=X      --->5=X
  183.           arr[k]=arr[j]^arr[k];               //3=X^3=5  
  184.           arr[j]=arr[j]^arr[k];               // X=X^5=3   换了
  185.      }

  186. }
复制代码
这里是测试结果



在随机生成数据下  基本就这样   冒泡(难道我的冒泡不是最优的?有更好的冒泡吗?我打印排序没错额   数据太多就没打印了 )最慢
     插入大于选择   快速和希尔差不多








2 个回复

倒序浏览
好东西,排序的整理。
回复 使用道具 举报
这个排序整理的不错,赞一个。
不同的情况适用不同的算法,单就随机生成的数据考察算法的优劣是不科学的。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马