归并排序和希尔排序

1  归并排序

归并排序是一种分治算法,把大的问题分成一个个小部分去处理,最终解决大问题。

 假设有两个数组A,B,每个数组都是从小到大排好序的,如果要将这两个数组合并成一个数组,并且从小到大排好序

那么只需要从头比较,依次将A,B中较小的值放入新的数组。

对于一个无序的数组,也可以通过这种方法排序,将数组从中间分成2部分,但是大概率是两个无序数组,然后接着对

分开的两部分再分,直到每部分都是只有一个数,显然每部分都是有序的了。如下图:

一.先分

二.比较排序再和 

 然后对最下一层两两比较,例如80  30   得到新的序列  [30,80]                       60   20  得到新的序列[20,60]

然后在对新序列[30,80]和[20,60]进行合并, 从头比较得到新的序列[20,30,60,80]         同理可得 右边的序列[10,50,60,70]     

 最后对[20,30,60,80] 和 [10,50,60,70]   进行合并,先创建一个新数组,长度等于两个数组长度的和,然后开始比较:

 10比20小,先将10存入; 将20和50比较,20小,将20存入;将50和30比较,30小,将30存入;50和60比较,50小,将50存入;60和60比较,将前面一个数组的60存入;然后接着60和80比较,60小,60存入新数组;80和70比较,70小,存入70,后面一个数组到头了的话,就把另一个数组的所有数据插入到新数组的末端;所有数据就被排好序了。

如图:

 代码实现

//第一步通过递归分
  public static void mergeSort(int []arr,int low,int high){
        int middle=(high+low)/2;
        if(low<high){
            //前半部分
            mergeSort(arr,low,middle);
            //后半部分
            mergeSort(arr,middle+1,high);
            //对排好序的进行归并
            merge(arr,low,middle,high);
        }
    }
  //第二步合并
 public static void merge(int []arr,int low,int middle,int high){
        int []temp=new int[high-low+1];
        int i=low;
        int j=middle+1;
        int index=0;
      //遍历前半部分和后半部分,一次将小的值存入新的数组
        while(i<=middle&&j<=high){
            if(arr[i]<=arr[j]){
                temp[index]=arr[i];
                i++;
                index++;
            }else {
                temp[index]=arr[j];
                j++;
                index++;
            }
        }
       //前半部分有剩余,就把剩下的全部存进去
        while(i<=middle){
            temp[index]=arr[i];
            index++;
            i++;
        }
        //后半部分有剩余,就把剩下的全部存进去
        while(j<=high){
            temp[index]=arr[j];
            index++;
            j++;
        }
        //将临时数组的数据存入原来数组
        for(int k=0;k<temp.length;k++){
            arr[low+k]=temp[k];
        }
    }

2  希尔排序

希尔排序是一种插入排序的优化,插入排序将一个数插入到前面合适的位置,如果很小的数一开始在队列的末端,那么比较的次数将会大大增加,希尔排序则解决了这个问题,能够快速的将队尾较小的值换到队前面,将大的值快速放到最后,减少比较次数

交换的步长从length/2开始,依次减半。开始时步长较大,比较次数较少,大元素基本放到最后,大致有序。最后步长短,比较次数多,不过队列基本有序状态,比较次数大大减少。

 public  static  void shellSort(int []arr){
        //步长从arr.length/2   --> 1      时间复杂度log2n
        for(int d=arr.length/2;d>0;d=d/2){
            //时间复杂度O(n)
            for(int i=d;i<arr.length;i++){
                int j=0;
                //时间复杂度O(1)
                //以d为步长比较i前面的值然后插入a[i]的值
                for(j=i;j>=d;j=j-d){
                    if(arr[j]<arr[j-d]){
                        int temp=arr[j];
                        arr[j]=arr[j-d];
                        arr[j-d]=temp;
                    }
                    else break;
                }
            }
        }
    }

猜你喜欢

转载自blog.csdn.net/qq_41800087/article/details/89927892