Swift 實(shí)現(xiàn) 7 種常見的排序算法

排序算法可以說是數(shù)據(jù)結(jié)構(gòu)與算法當(dāng)中最為基礎(chǔ)的部分陆爽,針對的是數(shù)組這一數(shù)據(jù)結(jié)構(gòu)缸托。將數(shù)組中的無序數(shù)據(jù)元素通過算法整理為有序的數(shù)據(jù)元素即為排序

算法一:插入排序
插入排序

插入排序(Insertion Sort)是一種簡單直觀的排序算法姥闪。它的工作原理是通過構(gòu)建有序序列蛔溃,對于未排序數(shù)據(jù)匾竿,在已排序序列中從后向前掃描瓦宜,找到相應(yīng)位置并插入。

步驟如下:
1. 從第一個元素開始岭妖,該元素可以認(rèn)為已經(jīng)被排序
2. 取出下一個元素临庇,在已經(jīng)排序的元素序列中從后向前掃描
3. 如果該元素(已排序)大于新元素反璃,將該元素移到下一位置
4. 重復(fù)步驟3,直到找到已排序的元素小于或者等于新元素的位置
5. 將新元素插入到該位置中
6. 重復(fù)步驟2
//MARK:- 插入排序
func insertSort(inout arr: [Int]) -> [Int] {
    
    for i in 1 ..< arr.count {
        let key = arr[i]
        var j = i - 1
        while j >= 0 && arr[j] > key {
            arr[j + 1] = arr[j]
            j -= 1
        }
        arr[j + 1] = key
    }
    return arr

}
算法二:希爾排序
希爾排序

希爾排序(Shell Sort)是插入排序的一種假夺。也稱縮小增量排序淮蜈,是直接插入排序算法的一種更高效的改進(jìn)版本。希爾排序是非穩(wěn)定排序算法侄泽。

步驟如下:
* 希爾排序是把記錄按下標(biāo)的一定增量分組礁芦,對每組使用直接插入排序算法排序;
* 隨著增量逐漸減少悼尾,每組包含的關(guān)鍵詞越來越多柿扣,當(dāng)增量減至1時,整個文件恰被分成一組闺魏,算法便終止未状。
//MARK:- 希爾排序
func shellSort(inout arr: [Int]) -> [Int] {
    var j: Int
    var gap = arr.count / 2
    while  gap > 0 {
        
        for i in 0 ..< gap {
            j = i + gap
            while j < arr.count {
                if arr[j] < arr[j - gap] {
                    let temp = arr[j]
                    var k = j - gap
                    while (k >= 0 && arr[k] > temp) {
                        arr[k + gap] = arr[k]
                        k -= gap
                    }
                    arr[k + gap] = temp
                }
                
                j += gap
            }

        }
        gap /= 2
        
    }

    return arr
}

備注:詳細(xì)的希爾排序解析

算法三:選擇排序
選擇排序

選擇排序(Selection sort)是一種簡單直觀的排序算法。它的工作原理如下析桥。首先在未排序序列中找到最小元素司草,存放到排序序列的起始位置,然后泡仗,再從剩余未排序元素中繼續(xù)尋找最小元素埋虹,然后放到排序序列末尾驹马。以此類推秩冈,直到所有元素均排序完畢。

步驟如下:
* 遍歷數(shù)組遂铡,找到最小的元素截亦,將其置于數(shù)組起始位置爬泥。
* 從上次最小元素存放的后一個元素開始遍歷至數(shù)組尾,將最小的元素置于開始處崩瓤。
* 重復(fù)上述過程袍啡,直到元素排序完畢。
//MARK:- 選擇排序
func selectionSort(inout arr: [Int]) -> [Int] {
    for i in 0 ..< arr.count - 1 {
        var min = i
        for j  in i+1 ..< arr.count {
            if arr[min] > arr[j] {
                min = j
            }
        }
        let temp = arr[min]
        arr[min] = arr[i]
        arr[i] = temp
    }   
    return arr
}
算法四:冒泡排序
冒泡排序

冒泡排序(Bubble Sort)是一種簡單的排序算法却桶。它重復(fù)地走訪過要排序的數(shù)列境输,一次比較兩個元素,如果他們的順序錯誤就把他們交換過來肾扰。走訪數(shù)列的工作是重復(fù)地進(jìn)行直到?jīng)]有再需要交換畴嘶,也就是說該數(shù)列已經(jīng)排序完成。這個算法的名字由來是因為越小的元素會經(jīng)由交換慢慢“浮”到數(shù)列的頂端集晚。

步驟如下:
* 比較相鄰的元素。如果第一個比第二個大区匣,就交換他們兩個偷拔,直到把最大的元素放到數(shù)組尾部蒋院。
* 遍歷長度減一,對剩下的元素從頭重復(fù)以上的步驟莲绰。
* 直到?jīng)]有任何一對數(shù)字需要比較時完成欺旧。
//MARK:- 冒泡排序
func bubbleSort(inout arr: [Int]) -> [Int] {
    for i in 0 ..< arr.count {
        for j in 0 ..< arr.count - 1 - i {
            if arr[j] > arr[j + 1] {
                let temp = arr[j]
                arr[j] = arr[j + 1]
                arr[j + 1] = temp
            }
        }
    } 
    return arr
}
算法五:歸并排序
歸并排序

歸并排序(Merge sort)是建立在歸并操作上的一種有效的排序算法。該算法是采用分治法(Divide and Conquer)的一個非常典型的應(yīng)用蛤签。

步驟如下:
1. 申請空間辞友,創(chuàng)建兩個數(shù)組,長度分別為兩個有序數(shù)組的長度
2. 設(shè)定兩個指針震肮,最初位置分別為兩個已經(jīng)排序序列的起始位置
3. 比較兩個指針?biāo)赶虻脑爻屏x擇相對小的元素放入到合并空間,并移動指針到下一位置
4. 重復(fù)步驟3直到某一指針達(dá)到序列尾
5. 將另一序列剩下的所有元素直接復(fù)制到合并序列尾
//MARK:- 歸并排序
func mergeSort(inout arr: [Int]) -> [Int] {
    
    func merge (inout arr: [Int], low: Int, mid: Int, high: Int, inout temp: [Int]) {
        var i = low
        var j = mid + 1
        let m = mid
        let n = high
        var k = 0
        
        while (i <= m && j <= n) {
            if (arr[i] <=  arr[j])
            {
                temp[k] = arr[i]
                k += 1
                i += 1
            }
            else
            {
                temp[k] = arr[j]
                k += 1
                j += 1
            }
        }
        
        while i <= m {
            temp[k] = arr[i]
            k += 1
            i += 1
        }
        
        while j <=  n {
            temp[k] = arr[j]
            k += 1
            j += 1
        }
        
        for f in 0 ..< k {
            arr[low + f] = temp[f]
        }
        
    }
    
    func internalMergeSort(inout arr: [Int], low: Int, high: Int, inout temp: [Int]) {
        if high <= low {
            return
        }
        let mid = low + (high - low) / 2
        // 左邊有序
        internalMergeSort(&arr, low: low, high: mid, temp: &temp)
        // 右邊有序
        internalMergeSort(&arr, low: mid + 1, high: high, temp: &temp)
        // 將兩邊合起來
        merge(&arr, low: low, mid: mid, high: high, temp: &temp)
    }
    
    var temp: [Int] = arr// 輔助數(shù)組
    internalMergeSort(&arr, low: 0, high: arr.count - 1, temp: &temp)
    return arr
}
算法六:快速排序
快速排序

快速排序(Quicksort)是對冒泡排序的一種改進(jìn)戳晌。它的基本思想是:通過一趟排序?qū)⒁判虻臄?shù)據(jù)分割成獨(dú)立的兩部分鲫尊,其中一部分的所有數(shù)據(jù)都比另外一部分的所有數(shù)據(jù)都要小,然后再按此方法對這兩部分?jǐn)?shù)據(jù)分別進(jìn)行快速排序沦偎,整個排序過程可以遞歸進(jìn)行疫向,以此達(dá)到整個數(shù)據(jù)變成有序序列。

步驟:
* 從數(shù)列中挑出一個元素豪嚎,稱為 “基準(zhǔn)”(pivot)搔驼,
* 重新排序數(shù)列,所有元素比基準(zhǔn)值小的擺放在基準(zhǔn)前面侈询,所有元素比基準(zhǔn)值大的擺在基準(zhǔn)的后面(相同的數(shù)可以到任一邊)舌涨。在這個分區(qū)退出之后,該基準(zhǔn)就處于數(shù)列的中間位置妄荔。這個稱為分區(qū)(partition)操作泼菌。
* 遞歸地(recursive)把小于基準(zhǔn)值元素的子數(shù)列和大于基準(zhǔn)值元素的子數(shù)列排序。
//MARK:- 快速排序
func quickSort(inout arr: [Int]) -> [Int] {
    func partition(p: Int, _ r: Int) -> Int {
        var i = p - 1
        let key = arr[r]
        for j in p ..< r {
            if arr[j] < key {
                i = i + 1
                let temp = arr[j]
                arr[j] = arr[i]
                arr[i] = temp
            }
        }
        arr[r] = arr[i + 1]
        arr[i + 1] = key
        return i + 1
    }
    
    func internalQuickSort(p: Int, _ r: Int) {
        if p < r {
            let q = partition(p, r)
            internalQuickSort(p, q - 1)
            internalQuickSort(q + 1, r)
        }
    }
    internalQuickSort(0, arr.count - 1)
    return arr
}
算法七:堆排序
s007.gif

堆排序(Heap Sort)是指利用堆這種數(shù)據(jù)結(jié)構(gòu)所設(shè)計的一種排序算法啦租。堆是一個近似完全二叉樹的結(jié)構(gòu)哗伯,并同時滿足堆性質(zhì):即子結(jié)點(diǎn)的鍵值或索引總是小于(或者大于)它的父節(jié)點(diǎn)。

步驟如下:
* 按堆的定義將數(shù)組R[0..n]調(diào)整為堆(這個過程稱為創(chuàng)建初始堆)篷角,交換R[0]和R[n]焊刹;
* 將R[0..n-1]調(diào)整為堆,交換R[0]和R[n-1]恳蹲;
* 重復(fù)上述過程虐块,直到交換了R[0]和R[1]為止。
//MARK:- 堆排序
func heapSort(inout arr: [Int]) -> [Int] {
    
    func buildheap(inout arr: [Int]) {
        let length = arr.count
        let heapsize = length
        var nonleaf = length / 2 - 1
        while nonleaf >=  0 {
            heapify(&arr, i: nonleaf, heapsize: heapsize)
            nonleaf -= 1
        }

    }
    
    func heapify(inout arr: [Int], i : Int, heapsize: Int){
        var smallest = i
        let left = 2*i+1
        let right = 2*i+2
        if(left < heapsize){
            if(arr[i]>arr[left]){
                smallest = left
            }
            else {
                smallest = i
            }
        }
        if(right < heapsize){
            if(arr[smallest] > arr[right]){
                smallest = right
            }
        }
        if(smallest != i){
            var temp: Int
            temp = arr[i]
            arr[i] = arr[smallest]
            arr[smallest] = temp
            heapify(&arr,i: smallest,heapsize: heapsize)
        }
        
    }
    
    func internalHeapSort(inout arr: [Int]) {
        var heapsize = arr.count
        buildheap(&arr)
        for _ in 0 ..< arr.count - 1 {
            var temp: Int
            temp = arr[0]
            arr[0] = arr[heapsize - 1]
            arr[heapsize - 1] = temp
            heapsize = heapsize - 1
            heapify(&arr, i: 0, heapsize: heapsize)
            
        }
        
    }
    
    internalHeapSort(&arr)
    return arr
}

參考

http://codecloud.net/sort-2208.html
http://wenzhiquan.github.io/2016/03/28/seven_sort/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末嘉蕾,一起剝皮案震驚了整個濱河市贺奠,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌错忱,老刑警劉巖儡率,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件挂据,死亡現(xiàn)場離奇詭異,居然都是意外死亡儿普,警方通過查閱死者的電腦和手機(jī)崎逃,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來眉孩,“玉大人个绍,你說我怎么就攤上這事±送簦” “怎么了巴柿?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長吟宦。 經(jīng)常有香客問我篮洁,道長,這世上最難降的妖魔是什么殃姓? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任袁波,我火速辦了婚禮,結(jié)果婚禮上蜗侈,老公的妹妹穿的比我還像新娘篷牌。我一直安慰自己,他們只是感情好踏幻,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布枷颊。 她就那樣靜靜地躺著,像睡著了一般该面。 火紅的嫁衣襯著肌膚如雪夭苗。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天隔缀,我揣著相機(jī)與錄音题造,去河邊找鬼。 笑死猾瘸,一個胖子當(dāng)著我的面吹牛界赔,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播牵触,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼淮悼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了揽思?” 一聲冷哼從身側(cè)響起袜腥,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎钉汗,沒想到半個月后瞧挤,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體锡宋,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡儡湾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年特恬,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片徐钠。...
    茶點(diǎn)故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡癌刽,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出尝丐,到底是詐尸還是另有隱情显拜,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布爹袁,位于F島的核電站远荠,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏失息。R本人自食惡果不足惜譬淳,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望盹兢。 院中可真熱鬧邻梆,春花似錦、人聲如沸绎秒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽见芹。三九已至剂娄,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間玄呛,已是汗流浹背阅懦。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留把鉴,地道東北人故黑。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像庭砍,于是被迫代替她去往敵國和親场晶。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 總結(jié)一下常見的排序算法怠缸。 排序分內(nèi)排序和外排序诗轻。內(nèi)排序:指在排序期間數(shù)據(jù)對象全部存放在內(nèi)存的排序。外排序:指在排序...
    jiangliang閱讀 1,346評論 0 1
  • Ba la la la ~ 讀者朋友們揭北,你們好啊扳炬,又到了冷鋒時間吏颖,話不多說,發(fā)車恨樟! 1.冒泡排序(Bub...
    王飽飽閱讀 1,797評論 0 7
  • 一半醉、直接插入排序 直接插入排序(Insertion Sort)的基本思想是:每次將一個待排序的元素記錄,按其關(guān)鍵字...
    kevin16929閱讀 561評論 0 0
  • 文/ Kurny 親愛的劝术,我的朋友 你愛的不是我啊 你愛的是一些人的陪伴 愛的是萬眾矚目的光環(huán) 當(dāng)有人把你像孩子似...
    Kurny91閱讀 165評論 0 1
  • 首先和各位小伙伴們道歉缩多,因為工作原因我暫時停止了更新。這篇文章是我在車上寫的养晋,為什么選擇這個題目呢衬吆?是因為我進(jìn)入集...
    職場菌閱讀 226評論 0 0