內部排序演算法(Golang版本)

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
package mainimport ("fmt")func main() {//儲存需要排序的Slicearr := []int{9, 3, 4, 7, 2, 1, 0, 11, 12, 11, 13, 4, 7, 2, 1, 0, 11, 12, 11}//實際用於排序的Slicelist := make([]int, len(arr))copy(list, arr)BubbleSortX(list)fmt.Println("冒泡排序:\t", list)copy(list, arr)QuickSort(list, 0, len(arr)-1)fmt.Println("快速排序:\t", list)copy(list, arr) //將arr的資料覆蓋到list,重設listInsertSort(list)fmt.Println("直接插入排序:\t", list)copy(list, arr)ShellSort(list)fmt.Println("希爾排序:\t", list)copy(list, arr)MergeSort(list)fmt.Println("二路歸併排序:\t", list)copy(list, arr)SelectSort(list)fmt.Println("簡單選擇排序:\t", list)copy(list, arr)HeapSort(list)fmt.Println("堆排序:     \t", list)}//region 冒泡排序//1,正宗的冒泡排序/*每趟排序過程中通過兩兩比較,找到第 i 個小(大)的元素,將其往上排。*/func BubbleSort(list []int) {var temp int // 用來交換的臨時數var i intvar j int// 要遍曆的次數for i = 0; i < len(list)-1; i++ {// 從後向前依次的比較相鄰兩個數的大小,遍曆一次後,把數組中第i小的數放在第i個位置上for j = len(list) - 1; j > i; j-- {// 比較相鄰的元素,如果前面的數大於後面的數,則交換if list[j-1] > list[j] {temp = list[j-1]list[j-1] = list[j]list[j] = temp}}}}//2,冒泡排序最佳化/*對冒泡排序常見的改進方法是加入標誌性變數exchange,用於標誌某一趟排序過程中是否有資料交換。如果進行某一趟排序時並沒有進行資料交換,則說明所有資料已經有序,可立即結束排序,避免不必要的比較過程。*/func BubbleSortX(list []int) {var exchange bool = falsevar temp int // 用來交換的臨時數var i intvar j int// 要遍曆的次數for i = 0; i < len(list)-1; i++ {// 從後向前依次的比較相鄰兩個數的大小,遍曆一次後,把數組中第i小的數放在第i個位置上for j = len(list) - 1; j > i; j-- {// 比較相鄰的元素,如果前面的數大於後面的數,則交換if list[j-1] > list[j] {temp = list[j-1]list[j-1] = list[j]list[j] = tempexchange = true}}if !exchange {break}exchange = false}}//endregion//region 快速排序func division(list []int, left int, right int) int {// 以最左邊的數(left)為基準var base int = list[left]for left < right {// 從序列右端開始,向左遍曆,直到找到小於base的數for left < right && list[right] >= base {right--}// 找到了比base小的元素,將這個元素放到最左邊的位置list[left] = list[right]// 從序列左端開始,向右遍曆,直到找到大於base的數for left < right && list[left] <= base {left++}// 找到了比base大的元素,將這個元素放到最右邊的位置list[right] = list[left]}// 最後將base放到left位置。此時,left位置的左側數值應該都比left小// 而left位置的右側數值應該都比left大。list[left] = base //此時left == right//fmt.Println("DONE: base:", base, "\tleft:", left, "\tright:", right)return left}func QuickSort(list []int, left int, right int) {// 左下標一定小於右下標,否則就越界了if left < right {//對數組進行分割,取出下次分割的基準標號var base int = division(list, left, right)//對“基準標號“左側的一組數值進行遞迴的切割,以至於將這些數值完整的排序QuickSort(list, left, base-1)//對“基準標號“右側的一組數值進行遞迴的切割,以至於將這些數值完整的排序QuickSort(list, base+1, right)}}//endregion//region 直接插入排序func InsertSort(list []int) {var temp intvar i intvar j int// 第1個數肯定是有序的,從第2個數開始遍曆,依次插入有序序列for i = 1; i < len(list); i++ {temp = list[i] // 取出第i個數,和前i-1個數比較後,插入合適位置// 因為前i-1個數都是從小到大的有序序列,所以只要當前比較的數(list[j])比temp大,就把這個數後移一位for j = i - 1; j >= 0 && temp < list[j]; j-- {list[j+1] = list[j]}list[j+1] = temp}}//endregion//region 希爾排序func ShellSort(list []int) {for gap := (len(list) + 1) / 2; gap >= 1; gap = gap / 2 {for i := 0; i < len(list)-gap; i++ {InsertSort(list[i:(gap + i + 1)]) //list[i:(gap + i + 1)]表示list索引i到gap+i的元素組成的slice}}}//region//region 簡單選擇排序/*簡單排序處理流程:(1)從待排序序列中,找到關鍵字最小的元素;(2)如果最小元素不是待排序序列的第一個元素,將其和第一個元素互換;(3)從餘下的 N - 1 個元素中,找出關鍵字最小的元素,重複(1)、(2)步,直到排序結束。*/func SelectSort(list []int) {var temp intvar index intvar i intvar j int// 需要遍曆獲得最小值的次數// 要注意一點,當要排序 N 個數,已經經過 N-1 次遍曆後,已經是有序數列for i = 0; i < len(list)-1; i++ {temp = 0index = i // 用來儲存最小值得索引// 尋找第i個小的數值for j = i + 1; j < len(list); j++ {if list[index] > list[j] {index = j}}// 將找到的第i個小的數值放在第i個位置上temp = list[index]list[index] = list[i]list[i] = temp}}//endregion//region 堆排序func heapAdjust(list []int, parent int, length int) {temp := list[parent]  // temp儲存當前父節點child := 2*parent + 1 // 先獲得左孩子for child < length {// 如果有右孩子結點,並且右孩子結點的值大於左孩子結點,則選取右孩子結點if child+1 < length && list[child] < list[child+1] {child++}// 如果父結點的值已經大於孩子結點的值,則直接結束if temp >= list[child] {break}// 把孩子結點的值賦給父結點list[parent] = list[child]// 選取孩子結點的左孩子結點,繼續向下篩選parent = childchild = 2*child + 1}list[parent] = temp}func HeapSort(list []int) {// 迴圈建立初始堆for i := len(list) / 2; i >= 0; i-- {heapAdjust(list, i, len(list)-1)}// 進行n-1次迴圈,完成排序for i := len(list) - 1; i > 0; i-- {// 最後一個元素和第一元素進行交換temp := list[i]list[i] = list[0]list[0] = temp// 篩選 R[0] 結點,得到i-1個結點的堆heapAdjust(list, 0, i)}}//endregion//region 歸併排序(二路歸併)func merge(list []int, low int, mid int, high int) {var i int = low                  // i是第一段序列的下標var j int = mid + 1              // j是第二段序列的下標var k int = 0                    // k是臨時存放定序序列的下標list2 := make([]int, high-low+1) // list2是臨時定序序列// 掃描第一段和第二段序列,直到有一個掃描結束for i <= mid && j <= high {// 判斷第一段和第二段取出的數哪個更小,將其存入定序序列,並繼續向下掃描if list[i] <= list[j] {list2[k] = list[i]i++k++} else {list2[k] = list[j]j++k++}}// 若第一段序列還沒掃描完,將其全部複製到定序序列for i <= mid {list2[k] = list[i]i++k++}// 若第二段序列還沒掃描完,將其全部複製到定序序列for j <= high {list2[k] = list[j]j++k++}// 將定序序列複製到原始序列中k = 0for i = low; i <= high; i++ {list[i] = list2[k]k++}}func MergeSort(list []int) {for gap := 1; gap < len(list); gap = 2 * gap {var i int// 歸併gap長度的兩個相鄰子表for i = 0; i+2*gap-1 < len(list); i = i + 2*gap {merge(list, i, i+gap-1, i+2*gap-1)}// 餘下兩個子表,後者長度小於gapif i+gap-1 < len(list) {merge(list, i, i+gap-1, len(list)-1)}}}//endregion

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.