排序算法(一):選擇排序、插入排序和希爾排序

一些說明

我將會寫一系列關於算法的博客,由於我是程序員,並非計算機科學家,也即我是搞工程的,並非搞學術的,因此對於我來講,最重要的就是程序員

1.有哪些算法算法

2.這些算法的原理數組

3.這些算法的實現ide

4.這些算法的效率spa

 

而其餘的,相對而言,並無那麼重要,好比算法的證實,因此之後的博客都會按照上述的思惟撰寫。code

 

1、首先定義一個抽象類,裏面集成了排序算法所須要的共同的方法blog

 

public abstract class SortBase {
    public abstract Integer[] sort(Integer[] a);
    
    public static void print(Integer[] arrayForSort) {
        System.out.print("[");
        for(int i=0;i<arrayForSort.length;i++) {
            if(i == arrayForSort.length - 1) {
                System.out.print(arrayForSort[i]);
            } else {
                System.out.print(arrayForSort[i] + " ,");
            }
        }
        System.out.println("]");
    }
    
    public static void print(String prefix,Integer[] arrayForSort) {
        System.out.print(prefix + ": ");
        System.out.print("[");
        for(int i=0;i<arrayForSort.length;i++) {
            if(i == arrayForSort.length - 1) {
                System.out.print(arrayForSort[i]);
            } else {
                System.out.print(arrayForSort[i] + " ,");
            }
        }
        System.out.println("]");
    }
}

 

2、選擇排序:排序

選擇排序能夠說是最簡單的一種排序方法:索引

1.找到數組中最小的那個元素博客

2.將最小的這個元素和數組中第一個元素交換位置

3.在剩下的元素中找到最小的的元素,與數組第二個元素交換位置

重複以上步驟,便可以獲得有序數組。

 

代碼以下:

public class SelectionSort extends SortBase {

    public Integer[] sort(Integer[] a) {
        print("init",a);
        Integer minIndex = 0;
        Integer temp = 0;
        for(int i=0;i<a.length;i++) {
            minIndex = i;
            for(int j=i+1;j<a.length;j++) {
                if(a[j] < a[minIndex]) {
                    minIndex = j;
                }
            }
            temp = a[i];
            a[i] = a[minIndex];
            a[minIndex] = temp;
            
            print((i+1) + "",a);
        }
        return a;
    }
    
    public static void main(String[] args) {
        Integer[] a = {2,1,5,9,0,6,8,7,3};
        print("result",(new SelectionSort()).sort(a));
    }
}

 

 

我在代碼中打出了每次排序的結果,運行結果以下:

init: [2 ,1 ,5 ,9 ,0 ,6 ,8 ,7 ,3]

1: [0 ,1 ,5 ,9 ,2 ,6 ,8 ,7 ,3]

2: [0 ,1 ,5 ,9 ,2 ,6 ,8 ,7 ,3]

3: [0 ,1 ,2 ,9 ,5 ,6 ,8 ,7 ,3]

4: [0 ,1 ,2 ,3 ,5 ,6 ,8 ,7 ,9]

5: [0 ,1 ,2 ,3 ,5 ,6 ,8 ,7 ,9]

6: [0 ,1 ,2 ,3 ,5 ,6 ,8 ,7 ,9]

7: [0 ,1 ,2 ,3 ,5 ,6 ,7 ,8 ,9]

8: [0 ,1 ,2 ,3 ,5 ,6 ,7 ,8 ,9]

9: [0 ,1 ,2 ,3 ,5 ,6 ,7 ,8 ,9]

result: [0 ,1 ,2 ,3 ,5 ,6 ,7 ,8 ,9]

 

效率:對於長度爲N的數組,選擇排序須要大約N²/2次比較和N次交換。也即最好、最差、平均時間效率均爲O(n²),只須要一個輔助變量幫助交換元素。

 

選擇排序能夠當作是冒泡排序的擴展,一個是把最小或最大的選出來,再交換,一個是一直交換直到最大最小的出如今正確的位置上,選擇排序相對於冒泡排序,比較次數是同樣的,可是交換次數要少不少。

 

3、插入排序:

插入排序相似整理撲克牌,將每一張牌插到其餘已經有序的牌中適當的位置。

插入排序由N-1趟排序組成,對於P=1到N-1趟,插入排序保證從位置0到位置P上的元素爲已排序狀態。

簡單的說,就是插入排序總共須要排序N-1趟,從index爲1開始,講該位置上的元素與以前的元素比較,放入合適的位置,這樣循環下來以後,即爲有序數組。

 

代碼實現:

public class InsertionSort extends SortBase {

    @Override
    public Integer[] sort(Integer[] a) {
        // TODO Auto-generated method stub
        print("init",a);
        Integer temp = 0;
        
        for(int i=1;i<a.length;i++) {
            //只能從當前索引往前循環,由於索引前的數組皆爲有序的,索引只要肯定當前索引的數據的爲止便可
            for(int j=i;j>0 && a[j] < a[j-1];j--) {
                temp = a[j];
                a[j] = a[j-1];
                a[j-1] = temp;
            }
            print(i +"",a);
        }
        
        print("result",a);
        return a;
    }
    
    public static void main(String[] args) {
        Integer[] a = {2,1,5,9,0,6,8,7,3};
        (new InsertionSort()).sort(a);
    }    
}

 

運行結果:

init: [2 ,1 ,5 ,9 ,0 ,6 ,8 ,7 ,3]

1: [1 ,2 ,5 ,9 ,0 ,6 ,8 ,7 ,3]

2: [1 ,2 ,5 ,9 ,0 ,6 ,8 ,7 ,3]

3: [1 ,2 ,5 ,9 ,0 ,6 ,8 ,7 ,3]

4: [0 ,1 ,2 ,5 ,9 ,6 ,8 ,7 ,3]

5: [0 ,1 ,2 ,5 ,6 ,9 ,8 ,7 ,3]

6: [0 ,1 ,2 ,5 ,6 ,8 ,9 ,7 ,3]

7: [0 ,1 ,2 ,5 ,6 ,7 ,8 ,9 ,3]

8: [0 ,1 ,2 ,3 ,5 ,6 ,7 ,8 ,9]

result: [0 ,1 ,2 ,3 ,5 ,6 ,7 ,8 ,9]

 

 

效率:若是目標是把n個元素的序列升序排列,那麼採用插入排序存在最好狀況和最壞狀況。最好狀況就是,序列已是升序排列了,在這種狀況下,須要進行的比較操做需(n-1)次便可。最壞狀況就是,序列是降序排列,那麼此時須要進行的比較共有n(n-1)/2次。插入排序的賦值操做是比較操做的次數加上 (n-1)次。平均來講插入排序算法的時間複雜度爲O(n^2)

 

 

4、希爾排序

把記錄按步長 gap 分組,對每組記錄採用直接插入排序方法進行排序。

隨着步長逐漸減少,所分紅的組包含的記錄愈來愈多,當步長的值減少到 時,整個數據合成爲一組,構成一組有序記錄,則完成排序。

 

實現代碼:

public class ShellSort extends SortBase {

    @Override
    public Integer[] sort(Integer[] a) {
        // TODO Auto-generated method stub
        print("init",a);
        Integer h = a.length;
        Integer temp = 0;
        while(h >= 1) {
            for(int i=h;i<a.length;i++) {
                for(int j=i;j>=h && a[j] < a[j-h];j -= h) {
                    temp = a[j];
                    a[j] = a[j-h];
                    a[j-h] = temp;
                    
                }
            }
            h /= 9;
        }
        print("result",a);
        return a;
    }
    
    public static void main(String[] args) {
        Integer[] a = {2,1,5,9,0,6,8,7,3};
        (new ShellSort()).sort(a);
    }
}

 

運行結果:

init: [2 ,1 ,5 ,9 ,0 ,6 ,8 ,7 ,3]

1: [0 ,1 ,5 ,7 ,2 ,6 ,8 ,9 ,3]

2: [0 ,1 ,2 ,6 ,3 ,7 ,5 ,9 ,8]

3: [0 ,1 ,2 ,3 ,5 ,6 ,7 ,8 ,9]

result: [0 ,1 ,2 ,3 ,5 ,6 ,7 ,8 ,9]

 

效率:

最壞狀況時間複雜度爲:O(n^1.5),平均時間複雜度爲O(nlogn)

相關文章
相關標籤/搜索