Java-數據結構篇-七種排序的簡要總結

總結:七種排序

一、冒泡排序(以下皆以從小到大排序爲例)

1.時間複雜度

平均情況:O(n^2)
最好情況:O(n)
最壞情況:O(n^2)

2.空間複雜度:O(1)
3.穩定性:穩定(沒有發生跳躍式的交換)
4.代碼示例
public static int[] bubbleSort(int[] arr) {
        if(arr == null || arr.length <= 1){
            return arr;
        }
        for(int i=0;i<arr.length-1;i++){
            int a=0;
            for(int j=0;j<arr.length-1-i;j++){//每次循環結束後最後一個元素爲當前最大元素
                if(arr[j]>arr[j+1]){//將大數往後移
                    int tmp=arr[j];
                    arr[j]=arr[j+1];
                    arr[j+1]=tmp;
                    a++;
                }
            }
            if(a==0){//所有數有序
                break;
            }
        }
        return arr;
}

二、選擇排序(從待排序數字的後面找到比當前待排序數字小的數字進行交換)

1.時間複雜度

平均情況:O(n^2)
最好情況:O(n^2)
最壞情況:O(n^2)

2.空間複雜度:O(1)
3.穩定性:不穩定(發生了跳躍式的交換)
4.代碼示例
public static int[] selectionSort(int[] arr) {
        for(int i = 0;i < arr.length;i++){
            for(int j = i + 1;j < arr.length;j++){
                if(arr[j] < arr[i]){
                    int tmp = arr[i];
                    arr[i] = arr[j];
                    arr[j] = tmp;
                }
            }
        }
        return arr;
}

三、直接插入排序(越有序越快)

1.時間複雜度

平均情況:O(n^2)
最好情況:O(n)
最壞情況:O(n^2)

2.空間複雜度:O(1)
3.穩定性:穩定
4.代碼示例
public static int[] insertionSort(int[] arr){
        for(int i = 1;i < arr.length;i++) {
            int tmp = arr[i],j=0;
            for (j = i - 1; j >= 0; j--) {
                if(arr[j] > tmp){//將比i大的往後移
                    arr[j+1] = arr[j];
                }else{
                    break;
                }
            }
            arr[j+1] = tmp;//將i放回
        }
        return arr;
}

四、Shell排序(組內進行有序(插入排序))

1.時間複雜度

平均情況:O(n^1.3)
最好情況:O(n)
最壞情況:O(n^2)

2.空間複雜度:O(1)
3.穩定性:不穩定
4.代碼示例
public static int[] shellSort(int[] arr,int gap) {
        for(int i = gap;i < arr.length;i++) {
           int tmp = arr[i], j = 0;
           for (j = i - gap; j >= 0; j = j - gap) {
                if(arr[j] > tmp){
                    arr[j + gap] = arr[j];
                }else{
                    break;
                }
            }
            arr[j + gap] = tmp;
        }
        return arr;
}

五、快速排序

1.時間複雜度

平均情況:O(nlog2n)
最好情況:O(nlog2n)
最壞情況:O(n^2)

2.空間複雜度:O(log2n)
3.穩定性:不穩定
4.代碼示例

         (1)快速排序的遞歸算法

public static int partion(int[] array,int low,int high){
        int tmp = array[low];
        int count = 1;
        while(low<high){
            if(count%2==1) {//利用count實現前後的輪替交換
                if (array[high]< tmp) {//從後面找小的
                    array[low]=array[high];
                    count++;
                }else {
                    high--;
                }
            }else {
                if(array[low]>tmp){//從前面找大的
                    array[high] = array[low];
                    count++;
                }else {
                    low++;
                }
            }
        }
        array[low]=tmp;
        return low;
}
public static void quick(int[] array,int low,int high){
        int par = partion(array,low,high);
        if(par > low+1){
            quick(array,low,par-1);
        }
        if(par<high-1){
            quick(array,par+1,high);
        }
}
public static void quickSort(int[] array){
        quick(array,0,array.length-1);
}

         (2)快速排序的非遞歸算法

 public static int partion(int[] array,int low,int high){
        int tmp = array[low];
        int count = 1;
        while(low<high){
            if(count%2==1) {
                if (array[high]< tmp) {
                    array[low]=array[high];
                    count++;
                }else {
                    high--;
                }
            }else {
                if(array[low]>tmp){
                    array[high] = array[low];
                    count++;
                }else {
                    low++;
                }
            }
        }
        array[low]=tmp;
        return low;
}
    public static void quickSort1(int[] array){
        int len = (int)(log((double)array.length)/log((double)2));
        int[] stack = new int[2*len];//用棧存儲low和high
        int top = 0 ;
        int low = 0 ;
        int high = array.length-1;
        int par = partion(array,low,high);
        if(par>low+1){
            stack[top] = low;
            top++;
            stack[top] = par-1;
            top++;
        }
        if(par<high-1){
            stack[top] = par+1;
            top++;
            stack[top] = high;
            top++;
        }
        while(top!=0){
            top--;
            high=stack[top];
            top--;
            low = stack[top];
            par = partion(array,low,high);
            if(par>low+1){
                stack[top] = low;
                top++;
                stack[top] = par-1;
                top++;
            }
            if(par<high-1){
                stack[top] = par+1;
                top++;
                stack[top] = high;
                top++;
            }
        }
}
5.快速排序的優化(以下兩種是對基準選取的優化)

         (1)隨機

public static int selectPivotRandom(int array[],int low,int high){
        Random random = new Random();
        int pivotPos = random.nextInt(high-low+1)+low;
        int tmp = array[low];
        array[low]=array[pivotPos];
        array[pivotPos]=tmp;
        return array[low];
}

         (2)取中

public static void midThree(int[] array,int low,int high){
        int mid = (high+low)/2;
        if(array[low]>array[high]){//實現mid<low<high
            int tmp = array[low];
            array[low]=array[high];
            array[high]=tmp;
        }
        if(array[mid]>array[low]){
            int tmp = array[low];
            array[low]=array[mid];
            array[mid]=tmp;
        }
        if(array[mid]>array[high]){
            int tmp = array[high];
            array[high]=array[mid];
            array[mid]=tmp;
        }
}

六、歸併排序(使每個子序列有序,再使子序列段間有序)

1.時間複雜度

平均情況:O(nlog2n)
最好情況:O(nlog2n)
最壞情況:O(nlog2n)

2.空間複雜度:O(n)
3.穩定性:穩定
4.代碼示例
public static void merge(int[] array,int gap){
        int[] tmpArr = new int[array.length];
        int i = 0;
        int s1 = 0;
        int e1 = s1+gap-1;
        int s2 = e1+1;
        int e2 = s2+gap-1 < array.length ? s2+gap-1:array.length-1;
        while(s2<array.length){
            while(s1<=e1&&s2<=e2){
                if(array[s1]<array[s2]){
                    tmpArr[i]=array[s1];
                    i++;
                    s1++;
                }
                if(array[s2]<array[s1]){
                    tmpArr[i]=array[s2];
                    i++;
                    s2++;
                }
            }
            if(s1>e1){
                while(s2<=e2){
                    tmpArr[i]=array[s2];
                    i++;
                    s2++;
                }
            }
            if(s2>e2){
                while(s1<=e1){
                    tmpArr[i]=array[s1];
                    i++;
                    s1++;
                }
            }
            s1 = e2+1;
            e1 = s1+gap-1;
            s2 = e1+1;
            e2 = s2+gap-1 < array.length ? s2+gap-1:array.length-1;
        }
        while(s1<array.length){
            tmpArr[i] = array[s1];
            i++;
            s1++;
        }
        for(int j = 0 ;j<array.length;j++){
            array[j] = tmpArr[j];
        }
}
    public static void mergeSort(int[] array){
        for(int i = 1;i<array.length;i*=2){//循環使每次的子段長度增加
            merge(array,i);
        }
    }

七、堆排(建立大根堆)

1.時間複雜度

平均情況:O(nlog2n)
最好情況:O(nlog2n)
最壞情況:O(nlog2n)

2.空間複雜度:O(1)
3.穩定性:不穩定
4.代碼示例
	public static void adjust(int[] array,int start,int end){
        int tmp = array[start];
        for (int i = 2*start+1; i <= end ; i = 2*i+1) {
            //判斷是否有右孩子,如果有,找到左右孩子的最大值。
            if((i < end) && array[i] < array[i+1]) {
                i++;
            }//肯定i是最大值的下標
            if(array[i] > tmp) {
                array[start] = array[i];
                start = i;
            }else {
                break;
            }
        }
        array[start] = tmp;
    }
    public static void heapSort(int[] array){
        for(int i = (array.length-1-1)/2;i>=0;i--){//建立大根堆
            adjust(array,i,array.length-1);
        }
        int tmp = 0;
        for (int i = array.length-1; i >0 ; i--) {
            tmp = array[i];
            array[i] = array[0];
            array[0]=tmp;
            adjust(array,0,i-1);
        }
    }

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章