1. 程式人生 > >排序算法系列:奇偶排序演算法

排序算法系列:奇偶排序演算法

概述

  在上一篇中我們說到了氣泡排序的原理及實現詳解。氣泡排序是一種交換排序,本文還是接著上一講,說說另一種交換排序演算法——奇偶排序。

版權說明

目錄

奇偶排序演算法

奇偶排序實際上在多處理器環境中很有用,處理器可以分別同時處理每一個奇數對,然後又同時處理偶數對。因為奇數對是彼此獨立的,每一刻都可以用不同的處理器比較和交換。這樣可以非常快速地排序。
                                     — 《Java資料結構和演算法》

演算法原理

  我不太清楚有多少人跟我一樣,看到奇偶排序的第一感覺是,對陣列中的奇數列和偶數列分別進行排序,再使用類似歸併排序中的合併操作使整體有序。
  不過,這裡的臆想並不是奇偶排序的思想,希望大家不要將上面的思路理解成奇偶排序。糾錯之後,讓我們來看看真正的奇偶排序是什麼樣的吧。
  奇偶排序的核心是,以奇數列為基準和以偶數列為基準對整個陣列進行排序。而排序的元素只有兩個,基準元素和其右側相鄰的一個元素。原理可參見下面的演算法原理圖。

演算法原理圖

這裡寫圖片描述

演算法步驟

  1. 選取所有奇數列的元素與其右側相鄰的元素進行比較,將較小的元素排序在前面;
  2. 選取所有偶數列的元素與其右側相鄰的元素進行比較,將較小的元素排序在前面;
  3. 重複前面兩步,直到所有序列有序為止。

演算法可行性證明

 在前一篇氣泡排序演算法,我們並沒有演算法可行性證明這一個點,原因是因為從它的原理或是過程圖中,我們可以從直觀上理解到它的可行性。而現在要說的奇偶排序則不一樣了,我們從上面的原理圖,無法得出此演算法就一定可行,所以在此給出一些比較簡單地演算法可行性證明過程。證明過程如下:

  1. 我們使用奇數排序+偶數排序,可以覆蓋陣列中的所有元素;
    1
  2. 針對一組操作(奇數排序+偶數排序),陣列中的所有元素形成鏈狀;2
  3. 假定一個元素為a[i],我們可以通過N次的奇偶交換排序,將a[i]沿著上面的鏈狀結構移動到合適的位置;
  4. 通過第3步的分析,我們可以將陣列中的所有元素移動到合適的位置,從而使整體有序。

演算法過程圖

這裡寫圖片描述

演算法實現

private void core(int[] array) {
        int arrayLength = array.length;
        boolean oddSorted = false;
        boolean evenSorted = false;

        while
(!oddSorted || !evenSorted) { int base = 0; oddSorted = true; evenSorted = true; for (int i = base; i < arrayLength - 1; i += 2) { if (array[i] > array[i + 1]) { ArrayUtils.swap(array, i, i + 1); oddSorted = false; } } base = 1; for (int i = base; i < arrayLength - 1; i += 2) { if (array[i] > array[i + 1]) { ArrayUtils.swap(array, i, i + 1); evenSorted = false; } } } }

演算法複雜度分析

排序方法 時間複雜度 空間複雜度 穩定性 複雜性
平均情況 最壞情況 最好情況
奇偶排序 O(nlog2n) O(nlog2n) O(n) O(1) 穩定 較簡單

Ref

GitHub原始碼下載

  1. 因為我們可以覆蓋所有的元素,所以才可以對全體元素進行排序,這一點是基礎。
  2. 可能大家對這一點不太明白,可是這一特徵是我們奇偶排序得以實現的關鍵一點。如果我們的元素在操作的過程中不能形成一個完整的鏈狀結構,也就是說陣列被分裂成兩個部分(或者多個部分),這樣部分之間不能交流,資訊被隔斷。排序就無從談起了。這一點保證了元素在整個陣列中的移動空間。