Golang-排序

1.冒泡排序

  • 步驟1: 比較相鄰的元素。如果第一個比第二個大,就交換它們兩個;
  • 步驟2: 對每一對相鄰元素作同樣的工作,從開始第一對到結尾的最後一對,這樣在最後的元素應該會是最大的數;
  • 步驟3: 針對所有的元素重複以上的步驟,除了最後一個;
  • 步驟4: 重複步驟1~3,直到排序完成。

image

func BubbleSort(array *[]int) {
	if array == nil {
		return
	}
	length := len(*array)
	for i := 0; i < length -1; i++ {
		flag := false
		for j := 0; j < length -1; j++ {
			if (*array)[j+1] < (*array)[j] {
				(*array)[j], (*array)[j+1] = (*array)[j+1], (*array)[j]
				flag = true
			}
		}
		if !flag {
			break
		}
	}
}

2.選擇排序

 n個記錄的直接選擇排序可經過n-1趟直接選擇排序得到有序結果。具體算法描述如下:

  • 步驟1:初始狀態:無序區爲R[1…n],有序區爲空;
  • 步驟2:第i趟排序(i=1,2,3…n-1)開始時,當前有序區和無序區分別爲R[1…i-1]和R(i…n)。該趟排序從當前無序區中-選出關鍵字最小的記錄 R[k],將它與無序區的第1個記錄R交換,使R[1…i]和R[i+1…n)分別變爲記錄個數增加1個的新有序區和記錄個數減少1個的新無序區;
  • 步驟3:n-1趟結束,數組有序化了。

image

func SelectSort(array *[]int) {
	if array == nil {
		return
	}
	length := len(*array)
	for i := 0; i < length-1; i++ {
		for j := i + 1; j < length; j++ {
			if (*array)[j] <= (*array)[i] {
				(*array)[i], (*array)[j] = (*array)[j], (*array)[i]
			}
		}
	}
}

3.插入排序

一般來說,插入排序都採用in-place在數組上實現。具體算法描述如下:

  • 步驟1: 從第一個元素開始,該元素可以認爲已經被排序;
  • 步驟2: 取出下一個元素,在已經排序的元素序列中從後向前掃描;
  • 步驟3: 如果該元素(已排序)大於新元素,將該元素移到下一位置;
  • 步驟4: 重複步驟3,直到找到已排序的元素小於或者等於新元素的位置;
  • 步驟5: 將新元素插入到該位置後;
  • 步驟6: 重複步驟2~5。

image

func InserSort(array *[]int) {
	if array == nil {
		return
	}
	length := len(*array)
	for i := 0; i < length; i++ {
		for j := i; j > 0; j-- {
			if (*array)[j] < (*array)[j -1] {
				(*array)[j], (*array)[j -1] = (*array)[j-1], (*array)[j]
			}
		}
	}
}

4.希爾排序

  先將整個待排序的記錄序列分割成爲若干子序列分別進行直接插入排序,具體算法描述:

  • 步驟1:選擇一個增量序列t1,t2,…,tk,其中ti>tj,tk=1;
  • 步驟2:按增量序列個數k,對序列進行k 趟排序;
  • 步驟3:每趟排序,根據對應的增量ti,將待排序列分割成若干長度爲m 的子序列,分別對各子表進行直接插入排序。僅增量因子爲1 時,整個序列作爲一個表來處理,表長度即爲整個序列的長度。

image

5.歸併排序 

  • 步驟1:把長度爲n的輸入序列分成兩個長度爲n/2的子序列;
  • 步驟2:對這兩個子序列分別採用歸併排序;
  • 步驟3:將兩個排序好的子序列合併成一個最終的排序序列。

image

//歸併
func merge(array *[]int, left, right int) {
	begin1 := left
	end1 := (left + right) / 2
	begin2 := end1 +1
	end2 := right

	pTemp := make([]int, right - left +1)
	count := 0

	//合併有序數組
	for begin1 < end1 && begin2 < end2 {
		if (*array)[begin1] < (*array)[begin2] {
			pTemp[count] = (*array)[begin1]
			begin1++
		} else {
			pTemp[count] = (*array)[begin2]
			begin2++
		}
		count++
	}

	for begin1 <= end1 {
		pTemp[count] = (*array)[begin1]
		begin1++
		count++
	}

	for begin2 <= end2 {
		pTemp[count] = (*array)[begin2]
		begin2++
		count++
	}

	count = 0
	for i := left ; i < right - left + 1; i++ {
		(*array)[i] = pTemp[count]
		count++
	}
}

func MergeSort(array *[]int, left, right int ) {
	if array == nil  {
		return
	}

	mid := (left + right) / 2
	if left < right {
		//拆分
		MergeSort(array, left, mid)
		MergeSort(array, mid + 1 , right)
		//合併
		merge(array, left, right)
	}
}

6.快排

快速排序使用分治法來把一個串(list)分爲兩個子串(sub-lists)。具體算法描述如下:

  • 步驟1:從數列中挑出一個元素,稱爲 “基準”(pivot );
  • 步驟2:重新排序數列,所有元素比基準值小的擺放在基準前面,所有元素比基準值大的擺在基準的後面(相同的數可以到任一邊)。在這個分區退出之後,該基準就處於數列的中間位置。這個稱爲分區(partition)操作;
  • 步驟3:遞歸地(recursive)把小於基準值元素的子數列和大於基準值元素的子數列排序。

image

func quickSortPartition(array *[]int, left int, right int) int {
	temp := (*array)[left]
	i := left +1
	j := right
	for i < j {
		for (*array)[j] > temp{
			j--
		}
		for (*array)[i] < temp {
			i++
		}
		if i < j {
			(*array)[i], (*array)[j] = (*array)[j], (*array)[i]
			continue
		}
		i++
	}
	(*array)[j], (*array)[left] = (*array)[left], (*array)[j]
	return j
}

func QuickSort(array *[]int, left int, right int) {
	length := len(*array)
	if length <= 0 || left < 0 || right > length - 1 || left > right{
		return
	}
	partition := quickSortPartition(array, left, right)
	QuickSort(array, left, partition -1)
	QuickSort(array, partition + 1, right)

}

7.堆排

  • 步驟1:將初始待排序關鍵字序列(R1,R2….Rn)構建成大頂堆,此堆爲初始的無序區;
  • 步驟2:將堆頂元素R[1]與最後一個元素R[n]交換,此時得到新的無序區(R1,R2,……Rn-1)和新的有序區(Rn),且滿足R[1,2…n-1]<=R[n];
  • 步驟3:由於交換後新的堆頂R[1]可能違反堆的性質,因此需要對當前無序區(R1,R2,……Rn-1)調整爲新堆,然後再次將R[1]與無序區最後一個元素交換,得到新的無序區(R1,R2….Rn-2)和新的有序區(Rn-1,Rn)。不斷重複此過程直到有序區的元素個數爲n-1,則整個排序過程完成。

image

// 小根堆
//length--需要調整的長度,index--第一個非葉子節點座標
func adjust(array *[]int, length int,  index int) {
	indexLeft := 2 *index +1
	indexRight := 2 *index +2
	maxIndex := index
	if indexLeft < length && (*array)[indexLeft] > (*array)[maxIndex] {
		maxIndex = indexLeft
	}
	if indexRight < length && (*array)[indexRight] > (*array)[maxIndex] {
		maxIndex = indexRight
	}
	if maxIndex != index {
		(*array)[maxIndex], (*array)[index] = (*array)[index], (*array)[maxIndex]
		adjust(array, length, maxIndex)
	}
}

func HeapSort(array *[]int) {
	if array == nil {
		return
	}
	length := len(*array)
	//構建大頂堆
	for i := length/2 -1; i >= 0; i-- {
		adjust(array, length, i)
	}
	//調整大頂堆,交換堆尾和堆首
	for i := length -1; i > 0; i-- {
		(*array)[0], (*array)[i] = (*array)[i], (*array)[0]
		//重建大頂堆,將前面無序堆調整成大頂堆
		adjust(array, i, 0)
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章