這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
歸併排序的基本思想
將待排序序列R[0...n-1]看成是n個長度為1的有序序列,將相鄰的有序表成對歸併,得到n/2個長度為2的有序表;將這些有序序列再次歸併,得到n/4個長度為4的有序序列;如此反覆進行下去,最後得到一個長度為n的有序序列。
綜上可知:
歸併排序其實要做兩件事:
(1)“分解”——將序列每次折半劃分。
(2)“合并”——將劃分後的序列段兩兩合并後排序。
歸併操作(merge),也叫歸併演算法,指的是將兩個順序序列合并成一個順序序列的方法。
如 設有數列{6,202,100,301,38,8,1}
初始狀態:6,202,100,301,38,8,1
第一次歸併後:{6,202},{100,301},{8,38},{1},比較次數:3;
第二次歸併後:{6,100,202,301},{1,8,38},比較次數:4;
第三次歸併後:{1,6,8,38,100,202,301},比較次數:4;
總的比較次數為:3+4+4=11,;
package algomithms
import "fmt"
type MergeSort struct {
}
func (object MergeSort) Sort(values []int) {
mergeSort(values)
}
func mergeSort(values []int) {
length := len(values)
gap := 1
for gap < length {
fmt.Println(" --merge by gap ", gap)
mergebygap(values, gap)
gap = gap * 2
fmt.Println(" --the tuple is ", values)
}
}
func mergebygap(values []int, gap int) {
length := len(values)
for i := 0; i < length; i += 2 * gap {
mergeTwoValues(values, i, gap)
}
}
func mergeTwoValues(values []int, start int, gap int) {
// fmt.Println(" ---- try to merge", values[start:start+gap], "and ", values[start+gap:start+2*gap])
length := len(values)
if start+gap >= length {
return
}
slice := make([]int, 2*gap)
lpos, rpos, slicepos := start, start+gap, 0
for lpos < start+gap && (rpos < start+2*gap && rpos < length) {
if values[lpos] <= values[rpos] {
slice[slicepos] = values[lpos]
lpos++
} else {
slice[slicepos] = values[rpos]
rpos++
}
slicepos++
}
if lpos != start+gap {
for lpos < start+gap {
slice[slicepos] = values[lpos]
lpos++
slicepos++
}
} else if rpos != start+2*gap && rpos != length {
for rpos < start+2*gap && rpos < length {
slice[slicepos] = values[rpos]
rpos++
slicepos++
}
}
for i := 0; i < slicepos; i++ {
values[i+start] = slice[i]
}
fmt.Println(" ---- merge result is ", slice[:slicepos])
// fmt.Println(" ---- merge result is ", values[start:start+2*gap])
}