常見排序算法--簡單排序


本文包括:

1.選擇排序

2.冒泡排序/雙向冒泡排序

3.插入排序

 

1.選擇排序

選擇排序是一種最為直觀的排序方法。每次循環從數組中選擇出一個最小或者最大的元素,按順序重新放入數組中,直到所有的戴排序元素都排序完成。

public void selectSort(int[] a){
        int temp=0;
        for(int i=0;i<a.length-1;i++){
            for(int j=i+1;j<a.length;j++){
                if(a[j]<a[i]){
                    temp = a[j];
                    a[j] = a[i];
                    a[i] = temp;
                }
            }
        }
    }

從代碼不難看出,選擇排序的過程是:第一次循環,遍歷數組找出數組中最小的數字,放入a[0],第二次循環,找出剩下數組中最小的數字放入a[1]一次類推。

所以,選擇排序的時間復雜度為O(n^2),如果n較大,則效率會非常低。

 

2.冒泡排序

冒泡排序也是較為簡單的一種排序方法,之所以叫冒泡排序,是因為排序的手法會使數字浮到數組頂端而得名。

冒泡排序的手法是:比較相鄰的兩個元素,如果相鄰的兩個元素的順序是錯誤的,則將他們交換;然后繼續比較下一組相鄰的元素。直到所有需要排列的元素都排序完成。

public void bubbSort(int[] a){
        int temp=0;
        for(int i=0;i<a.length-1;i++){
            for(int j=a.length-1;j>i;j--){
                if(a[j]<a[j-1]){
                    temp = a[j];
                    a[j] = a[j-1];
                    a[j-1] = temp;
                }
            }
        }
    }

從代碼我們可以看出來:冒泡排序是用層循環,外側循環的意義是在於,循環n次,每次冒泡都冒出最小的節點依次放在數組的最前面。第二層循環的意義是在於,進行冒泡操作,每次比較相鄰的兩個元素,將較小的元素,像數組頭方向移動。

因此我們可以看出冒泡排序的時間復雜度為O(n^2),如果n較大,則效率會非常低,如果數組是有序的,即進行一次冒泡掃描發現移動的關鍵次數為最小時,說明數組已經有序,此時的時間復雜度為O(n)。

 

雙向冒泡排序:

傳統的冒泡排序要么是從左向右進行,要么從右向左進行,每次都只對數組一頭的元素進行掃描排序。

而雙向冒泡排序首先從前往后把最大數移到最后,然后反過來從后往前把最小的一個數移動到數組最前面,這一過程就是第一輪,然后重復這一過程,最終就會把整個數組從小到大排列好。

public void bubbSort2(int[] a){
        int left =1 ;
        int right = a.length -1;
        int t=0;
        while(left<=right){
            for(int i=right;i>=left;i--){
                if(a[i]<a[i-1]){
                    int temp;
                    temp = a[i];
                    a[i] = a[i-1];
                    a[i-1] = temp;
                    t = i;//記錄上一次交換的下標
                }
            }
            left = t+1; //t+1中間亂序部分的最左端
            for(int i=left;i<right+1;i++){
                if(a[i]<a[i-1]){
                    int temp;
                    temp = a[i];
                    a[i] = a[i-1];
                    a[i-1] = temp;
                    t = i;//記錄上一次交換的下標
                }
            }
            right = t-1;//t-1為中間亂序部分的最右端
        }
    }

從代碼看來,雙向冒泡排序會比普通冒泡排序減少很多次循環。因為雙向排序時數組的兩頭都排序好了,我們只需要處理數組的中間部分即可,普通冒泡排序只有一頭的元素是排好序的。

雖然雙向冒泡排序有些改進,但是不能大幅度的提升效率,這是由於冒泡排序的基本過程所確定的。

 

3.插入排序

插入排序的基本方法是,每步將一個待排序的紀錄,按其關鍵碼值的大小插入前面已經排序的文件中適當位置上,直到全部插入完為止。

public void insertSort(int[] a){
        for(int i=1;i<a.length;i++){
            int temp = a[i],j=i    ;
            if(a[j-1]>temp){
                while(j>=1&&a[j-1]>temp){//找到新元素合適的位置
                    a[j] = a[j-1];//前一個覆蓋后一個
                    j--;
                }
            }
            a[j]=temp; //插入元素
        }
    }

直接插入排序最好的時間復雜度為O(n),平均時間復雜度為O(n^2)。同樣的,如果n過於大的時候,直接插入排序的效率會很低。

 

插入排序改進思路和冒泡排序一樣,我們也可以對於直接插入排序進行改進。在直接插入排序中我們每次插入元素的時候,都是挨個遍歷前面所有元素,這樣遍歷的效率並不高。

因為插入的數組是已經排好序的有序數組,所以我們自然而然的想到了折半插入的方法,這樣可以減少比較的次數。

不過雖然折半插入會減少元素比較的次數,但因為是插入數組,所以,只是減少元素的比較次數,元素移動的個數依然沒有改變,時間復雜度依然是O(n^2)。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM