詳解排序算法--插入排序和冒泡排序

  • 冒泡排序
  • 插入排序
  • 插入排序和冒泡排序分析

冒泡排序

Paste_Image.png

冒泡排序(英語:Bubble Sort,臺灣另外一種譯名為:泡沫排序)是一種簡單的排序算法。它重復地走訪過要排序的數列,一次比較兩個元素,如果他們的順序錯誤就把他們交換過來。走訪數列的工作是重復地進行直到沒有再需要交換,也就是說該數列已經排序完成。盡管這個算法是最簡單了解和實現的排序算法之一,但它對于包含大量的元素的數列排序是很沒有效率的。

冒泡排序算法的運作如下:

  • 比較相鄰的元素。如果第一個比第二個大,就交換他們兩個。
  • 對每一對相鄰元素作同樣的工作,從開始第一對到結尾的最后一對。這步做完后,最后的元素會是最大的數。
  • 針對所有的元素重復以上的步驟,除了最后一個。
  • 持續每次對越來越少的元素重復上面的步驟,直到沒有任何一對數字需要比較。

冒泡排序如果能在內部循環第一次運行時,使用一個旗標來表示有無需要交換的可能,也可以把最壞情況下的復雜度降低到{O(n)}
在這個情況,已經排序好的數列就無交換的需要。

  • 最壞時間復雜度
O(n^{2})
O(n^{2})
  • 最優時間復雜度
O(n)
O(n)
  • 平均時間復雜度
O(n^{2})
O(n^{2})
  • 空間復雜度
    總共{O(n)}
    需要輔助空間{O(1)}

  • 穩定的排序

冒泡排序的動態圖:

201111301912294589.gif

Java代碼實現:

package cc;

public class BubbleSort {
    
    public static void bubblesort(int[] a) {
        bubblesort(a, 0, a.length-1);
    }
    
    private static void bubblesort(int[] a, int left, int right) {
        
        for(int p=right;p>=left;p--) {
            int flag = 0;
            for(int i=0;i<p;i++) {
                if(a[i] > a[i+1]) {
                    swap(a, i, i+1);
                    flag = 1;
                }
            }
            if(flag == 0)
                break;
        }
    }

    private static void swap(int[] a, int i, int j) {
        
        int temp = a[i];
        a[i] = a[j];
        a[j] = temp;
        
    }
}

插入排序

類似于摸牌的過程

Paste_Image.png

插入排序(英語:Insertion Sort)是一種簡單直觀的排序算法。它的工作原理是通過構建有序序列,對于未排序數據,在已排序序列中從后向前掃描,找到相應位置并插入。插入排序在實現上,通常采用in-place排序(即只需用到O(1)的額外空間的排序),因而在從后向前掃描過程中,需要反復把已排序元素逐步向后挪位,為最新元素提供插入空間。

算法描述:

  • 從第一個元素開始,該元素可以認為已經被排序
  • 取出下一個元素,在已經排序的元素序列中從后向前掃描
  • 如果該元素(已排序)大于新元素,將該元素移到下一位置
  • 重復步驟3,直到找到已排序的元素小于或者等于新元素的位置
  • 將新元素插入到該位置后
  • 重復步驟2~5

如果比較操作的代價比交換操作大的話,可以采用二分查找法來減少比較操作的數目。該算法可以認為是插入排序的一個變種,稱為二分查找插入排序

  • 最壞時間復雜度
O(n^{2})
O(n^{2})
  • 最優時間復雜度
O(n)
O(n)
  • 平均時間復雜度
O(n^{2})
O(n^{2})
  • 空間復雜度
    總共{O(n)}
    需要輔助空間{ O(1)}

  • 穩定的排序

插入排序動態圖:

Insertion-sort-example-300px.gif
Insertion_sort_animation.gif

Java代碼

package cc;

public class InsertSort {

    public static void insertsort(int[] a) {
        insertsort(a, 0, a.length-1);
    }
    
    private static void insertsort(int[] a, int left , int right) {
        int j;
        
        for(int p = left+1;p<=right;p++) {
            int temp = a[p];
            for(j=p;j>left && a[j-1] > temp;j--)
                a[j] = a[j-1];
            a[j] = temp;
        }
    }
}

插入排序和冒泡排序分析

首先我們引入逆序對的概念

對于下標i<j,如果A[i]>A[j],則稱(i,j)是一對逆序對(inversion)

交換2個相鄰元素正好消去1個逆序對!

給定初始序列{34, 8, 64, 51,32, 21},冒泡排序和插入排序分別需要多少次元素交換才能完成?
交換次數就是逆序對的次數,都是9次

插入排序: T(N, I) = O( N+I ),如果序列基本有序,則插入排序簡單且高效

定理:任意N個不同元素組成的序列平均具有N ( N - 1 ) / 4 個逆序對。

定理:任何僅以交換相鄰兩元素來排序的算法,其平均時間復雜度為 ( N2 ) 。 這意味著:要提高算法效率,我們

  • 每次消去不止1個逆序對!
  • 每次交換相隔較遠的2個元素!

這就是希爾排序的由來。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 該篇文章主要介紹了算法基礎以及幾種常見的排序算法:選擇排序、插入排序、冒泡排序、快速排序、堆排序。 一、算法基礎 ...
    ZhengYaWei閱讀 1,269評論 0 12
  • Ba la la la ~ 讀者朋友們,你們好啊,又到了冷鋒時間,話不多說,發車! 1.冒泡排序(Bub...
    王飽飽閱讀 1,816評論 0 7
  • 眉湖池畔,月下石上,想乘風納涼,卻水波不興,岸樹不動;乍起水花,偶來蛙鳴,聽魚蛙且樂,而我自落寞,獨喂蚊蟲。
    山長說閱讀 155評論 0 1
  • 我去過離你很近的地方 也曾駐足長亭外 遙望你去的遠方 只有這樣 我才不會惆悵
    栩芠閱讀 200評論 3 1
  • 今天是美育特色課程的一天,我們高高興興地來了教室等老師來給我們講怎么做。 老師來了以后我們要興...
    祥頤閱讀 298評論 0 0