部分排序算法總結

關於排序

一般所說的排序是指內部排序,即在內存裏進行排序。相對應的有外部排序,當待排序數據比較多時,排序過程須要使用閃存。算法

排序算法大致可分爲兩種:
一種是比較排序,時間複雜度O(nlogn) ~ O(n^2),主要有:冒泡排序,選擇排序,插入排序,歸併排序,堆排序,快速排序等。
另外一種是非比較排序,時間複雜度能夠達到O(n),主要有:計數排序,基數排序,桶排序等。數組

排序算法穩定性說明:若是待排序序列A中兩個元素相等,即Ai = Aj,排序前Ai在Aj以前,排序後Ai還在Aj以前,則稱這種排序算法是穩定的。就是保證排序先後兩個相等的元素的相對順序不變ui

如下爲各算法的時間複雜度等對比spa

排序 平均 最優 最差 輔助空間 是否穩定
冒泡排序 O(n2) O(n) O(n2) O(1) 穩定
簡單選擇排序 O(n2) O(n2) O(n2) O(1) 不穩定
直接插入排序 O(n2) O(n) O(n2) O(1) 穩定
快速排序 O(nlogn) O(nlogn) O(n2) O(logn)-O(n) 不穩定
希爾排序 O(nlogn)-O(n2) O(n1.3) O(n2) O(1) 不穩定
歸併排序 O(nlogn) O(nlogn) O(nlogn) O(n) 穩定
堆排序 O(nlogn) O(nlogn) O(nlogn) O(n) 不穩定

一些共用方法

main包用來執行,myAlgo包爲具體方法實現3d

//如下爲共用方法

//交換兩個元素位置
package myAlgo
func exchange(arr []int, a int, b int) {
    temp := arr[a]
    arr[a] = arr[b]
    arr[b] = temp
}

//返回序列最小值下標
func selectMin(arr []int, i int) int {
    length := len(arr)
    minKey := i
    minValue := arr[minKey]
    //從下標爲i及以後的元素中找出值最小的元素
    for k := minKey + 1; k < length; k++ {
        if minValue > arr[k] {
            //修改下標
            minKey = k
            minValue = arr[k]

        }
    }
    return minKey
}

一、冒泡排序

冒泡排序算法運行方式以下:
假設待排序序列有n個元素
第一次循環
1.從首元素開始比較相鄰的元素,若是順序不對,就把它們兩個調換位置,直至最後一個,此時能夠保證最後一個元素是最大的(或最小的)
2.重複以上操做,每次循環均可以將無序序列(序列無序元素數量每次循環後都在減小)最大(最小)的一個元素移至最右邊,因此第k次循環後前n-k個元素是無序的,後k個元素是有序且依次遞增(遞減)的code

示意圖blog

圖片描述

package main

import (
    "fmt"
    "myAlgo"
)

func main() {
    arr := []int{15, 45, 42, 25, 20, 63, 23, 20, 29, 100, 9}
    myALgo.BubbleSort(arr);
}

package myAlgo
import "fmt"
func bubbleSort(arr []int) {
    length := len(arr)
    for j := length - 1; j > 0; j-- {
        //外層循環控制循環次數
        for i := 0; i < j; i++ {
            //內層循環控制交換
            if arr[i] > arr[i+1] {
                //交換順序
                exchange(arr, i, i+1)
            }
        }
        fmt.Println(arr)
    }
}

結果以下排序

clipboard.png

二、簡單選擇排序

思路以下:
1.首先,找到序列中最小的那個元素,將它和第一個元素交換位置。
2.在剩下的元素中找到最小元素,將它與序列的第二個元素交換位置
3.按照以上方式如此往復,直至將整個序列排序。
由於它在不斷的選擇剩餘元素之中的最小者,因此叫選擇排序。遞歸

示意圖
圖片描述圖片

go實現

package main
import "fmt"
func main() {
    arr := []int{15, 45, 42, 25, 20, 63, 23, 20, 29, 100, 9}
    fmt.Println(arr)    
    myAlgo.SelectSort(arr)
}

package myAlgo
import "fmt"
func SelectSort(arr []int) {
    fmt.Println("開始排序")
    length := len(arr)
    for i := 0; i < length; i++ {
        //每循環一次都找出當前未排序元素中的最小值,和當前元素進行交換
        minKey := selectMin(arr, i)
        exchange(arr, i, minKey)
    }
    fmt.Println(arr)
}

執行結果
clipboard.png

三、直接插入排序

這個相似於玩撲克牌,一張一張的將牌拿出來插到部分已經有序序列中的合適位置,具體以下:
1.第一個元素能夠當作是有序的
2.從有序序列下一個元素開始,用這個元素a從後向前,依次和有序序列元素b進行比較,若是元素a小於元素b,則將元素a插入到元素b以前,原有序序列b以後的元素均向後移動一個位置,此時生成一個新的有序序列。
3.重複操做2

示意圖
圖片描述

go實現

package main

import (
    "fmt"
    "myAlgo"
)
func main() {
    arr := []int{15, 45, 42, 25, 20, 63, 23, 20, 29, 100, 9}
    fmt.Println(arr)
    myAlgo.InsertSort(arr)
}

package myAlgo
import "fmt"
func InsertSort(arr []int) {
    fmt.Println("開始排序")
    //獲取當前數組長度
    length := len(arr)
    for i := 1; i < length; i++ {
        //當前值
        now := arr[i]
        //若是當前元素小於以前序列中的某一個元素的值,則序列今後元素向後總體移動一位
        for j := i - 1; j >= 0; j-- {
            if now < arr[j] {
                arr[j+1] = arr[j]
                arr[j] = now
            } else {
                arr[j+1] = now
                break
            }
        }
        fmt.Println(arr)
    }
}

運行結果

clipboard.png

快速排序

算法原理:
將未排序元素根據一個做爲基準的「主元」(Pivot)分爲兩個子序列,其中一個子序列的記錄均大於主元,而另外一個子序列均小於主元,而後遞歸地對這兩個 子序列用相似的方法進行排序。本質上,快速排序使用分治法,將問題的規模減少,而後再分別進行處理。

示意圖
圖片描述

go實現

package main

import (
    "fmt"
    "myAlgo"
)
func main() {    
    arr := []int{40, 45, 42, 25, 20, 63, 23, 20, 50, 29, 100, 9}
    fmt.Println(arr)    
    myAlgo.QuickSort(arr, 0, len(arr) - 1)
}

package myAlgo
import "fmt"
func QuickSort(arr []int, left int, right int) {

    //設置基準數,選擇第一個做爲基準數
    baseKey := left
    baseValue := arr[baseKey]
    fmt.Println("當前序列", arr[left:right+1],"基準值爲",baseValue)
    fmt.Println("開始排序")
    i := left
    j := right
    for i < j {
        //先從右向左找,直到找到一個小於基準數的值
        for (arr[j] >= baseValue) && (i < j) {
            j--
        }
        if i < j {
            //將j的值放到i的空位上
            arr[i] = arr[j]

        }
        //從左向右找,直到找到一個大於基準數的值
        for (i < j) && (arr[i] < baseValue) {
            i++
        }
        if i < j {
            //將此時的i放到以前j產生的空位上
            arr[j] = arr[i]
        }
        fmt.Println(arr[left:right+1])

    }
    arr[i] = baseValue
    fmt.Println("子序列結果", arr[left:right+1])
    fmt.Println("總序列", arr)
    fmt.Println("--------------------")
    if left < i-1 {
        QuickSort(arr, left, i-1)
    }
    if i+1 < right {
        QuickSort(arr, i+1, right)
    }

}

運行結果

clipboard.png

clipboard.png

相關文章
相關標籤/搜索