Golang 實現插入排序的方法示例(2種)
阿新 • • 發佈:2020-02-13
再次研究了插入排序的概念:定義一個有序的資料序列a,將待排序的序列b中的數依次插入到a的合適位置,插入後仍然有序
總結其與冒泡、選擇的區別在於,內部迭代的次數是逐漸增大的,二後兩者隨著排序進行迭代次數逐漸減少
嘗試基於Go的實現:
插入排序都採用in-place在陣列上實現。具體演算法描述如下:
- 從第一個元素開始,該元素可以認為已經被排序 取出下一個元素
- 在已經排序的元素序列中從後向前掃描
- 如果該元素(已排序)大於新元素,將該元素移到下一位置
- 重複步驟3,直到找到已排序的元素小於或者等於新元素的位置 將新元素插入到該位置後
- 將新元素插入到該位置後
- 重複步驟2~5
兩種實現方式:1,新建切片; 2,在原切片中進行元素交換
方式一:新建切片
package main import "fmt" func main() { arr := []int{1,5,7,8,3,6,9,2,54,33,66} newArr := []int{} insertionSort(arr,&newArr) fmt.Println(newArr) } /** 插入排序法:取原陣列old中第一個值作為新陣列中的第一個值,然後遍歷old,將每個元素按照條件插入到新陣列中 時間複雜度:O(n^2) */ func insertionSort(old []int,new *[]int) { if len(*new) == len(old) { return } current := len(*new) *new = append(*new,old[current]) sort(*new) insertionSort(old,new) } func sort(arr []int) { for i := len(arr) - 1; i > 0; i-- { if arr[i] < arr[i-1] { arr[i],arr[i-1] = arr[i-1],arr[i] } } }
注意:insertionSort()函式中的第二個引數為切片的指標,不然打印出來的的新陣列為空
原因:雖然切片是指標傳遞,這是指切片內的各個元素是指標傳遞,對於切片本身仍是值傳遞
證明:
package test import ( "fmt" "testing" ) func TestSlice(t *testing.T) { slice1 := []string{"zhang","san"} fmt.Printf("%p\n",&slice1) fmt.Printf("%p\n",&slice1[1]) modify(slice1) fmt.Println(slice1) } func modify(data []string) { fmt.Printf("%p\n",&data) fmt.Printf("%p\n",&data[1]) data[1] = "si" }
列印結果:
0xc0420e4680
0xc0420e46b0
0xc0420e46c0
0xc0420e46b0
[zhang si]
引申:Go 語言裡的引用型別有如下幾個:切片、對映、通道、介面和函式型別。當宣告上述型別的變數時,建立的變數被稱作標頭(header)值。從技術細節上說,字串也是一種引用型別。每個引用型別建立的標頭值是包含一個指向底層資料結構的指標。因為標頭值是為複製而設計的,所以永遠不需要共享一個引用型別的值。標頭值裡包含一個指標,因此通過複製來傳遞一個引用型別的值的副本,本質上就是在共享底層資料結構
結論:不會對切片進行增加或刪除操作時(也就是長度不會改變),切片作為引數在函式間的傳遞不需使用指標。但是如果切片需要進行增加或刪除元素的操作,並且原函式需要呼叫更新後的切片,那麼在原函式呼叫其它函式時,就需要用切片的指標作為引數。
方式二:在原切片中進行元素交換
func method2(arr []int) { if len(arr) < 2 { return } for i := 1; i < len(arr); i++ { for j := i; j > 0; j-- { if arr[j] < arr[j-1] { arr[j],arr[j-1] = arr[j-1],arr[j] } } } }
由於不用建立新的切片,不用進行插入操作,只需要交換操作,所以要較方法一速度快些
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。