希尔排序、快速排序、归并排序(Java实现)

Shell Sort 希尔排序

插入排序的改进版本。

将初始序列按照等间隔取值的方式分为若干个子序列,对子序列进行插入排序。

选取子序列时,子序列中相邻元素在初始序列中的序号之差称为增量

缩小增量,多次进行插入排序,每次都使整个序列趋近有序,在最后一次插入排序时(此时增量为1)整个序列已经是高度有序的。

伪代码实现

(以增量每次减半为例)

for(int i=array.length/2;i>2;i/=2){//遍历每个增量,i是增量

        for(int j=0;j<i;j++)//遍历增量下的每个子序列,j是每个子序列第一个元素在原序列中的序号

                InsertSort(array,j,i);//传入首元素序号和增量,函数即可取出整个子序列进行插入排序

InsertSort(array,0,1);//无论增量如何缩小,最后一次插入排序的增量必须是1

}

其实是真代码()不过写伪代码实现也只是为了容易理解,这个就是比较好理解的代码片段

复杂度分析

时间复杂度:平均O(n^1.5)

        直接插入排序的平均情况为O(n^2)。

        希尔排序的时间复杂度为每次调用插入排序时的交换次数求和。这个值和增量有关,具体计算可以参考这里

空间复杂度:O(1)

Java代码

import java.util.Arrays;

public class TestClass {
    static int[] array= new int[]{5, 6, 3, 4, 9, 2, 7, 0, 1, 8};
    static  void ShellSort(int[] array){
        for(int i=array.length/2;i>1;i/=2){
            for(int j=0;j<i;j++)
                InsertSort(array,j,i);
            InsertSort(array,0,1);

        }
    }
    static void InsertSort(int[] array,int start,int increment){
        for(int i=start+increment;i<array.length;i+=increment)
            for (int j = i; j >= increment; j-=increment)
                if(array[j]<array[j-increment]){
                    int tmp=array[j-increment];
                    array[j-increment]=array[j];
                    array[j]=tmp;
                }
    }
    public static void main(String[] args){
        ShellSort(array);
        System.out.println(Arrays.toString(array));
    }
}

Quick Sort 快速排序

选取一个轴值,每次使序列前半部分小于轴值,使后半部分大于轴值

伪代码实现

quicksort (第一个元素序号s,最后一个元素序号t,array){
        if (s < t){
                int pivot = 轴值位置, 左边界left = s, 右边界right = t;
                交换array[s]和array[pivot]//把轴值放在最左边
                while (left < right){
                    while (left < right && array[right] >= array[s]) right--;//将j前移直到出现小于轴值的元素
                    while (left < right && array[left] <= array[s]) left++;//将j前移直到出现大于轴值的元素
                    交换array[left]和array[right];
                }//得到前一部分小于轴值,后一部分大于等于轴值的序列
                交换array[left]和array[s]//把轴值放在左右边界相遇的位置
                quicksort(s, left-1, array);
                quicksort(left + 1, t, array);//递归调用
        }

Java代码

import java.util.Arrays;

public class TestClass {
    static int[] array= new int[]{5, 6, 3, 8, 4, 11, 54, 78, 0, 4, 4, 9, 2, 7, 0, 1, 8};
    static void QuickSort(int s,int t,int[] array){
        if(s<t){
            int pivot=(s+t)/2,l=s,r=t;
            int pivotval=array[pivot];
            array[pivot]=array[s];
            array[s]=pivotval;
            while(l<r){
                while(l<r&&array[r]>=array[s])r--;
                while(l<r&&array[l]<=array[s])l++;
                int tmp=array[r];
                array[r]=array[l];
                array[l]=tmp;
            }
            array[s]=array[l];
            array[l]=pivotval;
            if(s<r-1)QuickSort(s,r-1,array);
            if(r+1<t)QuickSort(r+1,t,array);
        }
    }
    public static void main(String[] args){
        QuickSort(0, array.length-1, array);
        System.out.println(Arrays.toString(array));
    }
}

Mergesort归并排序

将序列分割,再两两有序合并

分别从两个序列取未被处理的数中最靠前的数,将这两个数中较小的放到输出数组的第一个位置

伪代码实现

mergesort (待排序列/输出数组array,临时数组temp,第一个元素序号s,最后一个元素序号t,array){
        if(s==t)return;//只有一个元素,返回
        int 分割位置mid=(s+t)/2,左子序列开头序号sub1=s,右子序列开头序号sub2=mid+1;
        mergesort(array,temp,s,mid);
        mergesort(array,temp,mid,t);//递归调用
        for(int i=1;i<=r;i++)temp[i]=array[i];//将序列复制到临时数组
        for(int i=s;i<=r;i++){//将临时数组中的元素按排序规则放到array中
                if(sub1=mid+1)//左子序列用完了(但是既然temp没满,右子序列肯定还有
                    array[i]=temp[sub2++];
                else if(sub2>t)//右子序列用完了
                    array[i]=temp[sub1++];
                else array[i]=temp[sub1]<=temp[sub2]?temp[sub1++]:temp[sub2++]
        }
}

Java代码

import java.util.Arrays;

public class TestClass {
    static int[] array= new int[]{5, 6, 3, 8, 4, 11, 54, 78, 0, 4, 4, 9, 2, 7, 0, 1, 8};
    static int[] tmp=new int[array.length];
    static void MergeSort(int[] arr, int[] tmp, int s, int t) {
        if(s==t)return;
        int mid = (s + t)/2;
        MergeSort(arr, tmp, s, mid);
        MergeSort(arr, tmp, mid+1, t);
        int leftsub=s,rightsub=mid+1;
        if (t + 1 - s >= 0) System.arraycopy(arr, s, tmp, s, t + 1 - s);
        for(int i=s;i<=t;i++){
            if(leftsub==mid+1)arr[i]=tmp[rightsub++];
            else if(rightsub>t)arr[i]=tmp[leftsub++];
            else arr[i]=tmp[rightsub]<=tmp[leftsub]?tmp[rightsub++]:tmp[leftsub++];
        }
    }
    public static void main(String[] args){
        MergeSort(array, tmp, 0,array.length-1);
        System.out.println(Arrays.toString(array));
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值