12.マージソート

マージソート

最初に配列を中央から2つの部分に分割し、次に2つの部分を個別にソートしてから、2つの部分を順番にマージして、配列全体が順序付けられるようにします

心を分割し、分割し、支配する。

分割統治は問題解決の考え方であり、再帰はプログラミングスキルです

再帰的な式:

merge_sort(p…r)= merge(merge_sort(p…q)、merge_sort(q + 1…r))

終了条件:p> = rは分解を続ける必要がなくなりました

疑似コード:

// 归并排序算法, A 是数组,n 表示数组大小
merge_sort(A, n) {
  merge_sort_c(A, 0, n-1)
}

// 递归调用函数
merge_sort_c(A, p, r) {
  // 递归终止条件
  if p >= r  then return

  // 取 p 到 r 之间的中间位置 q
  q = (p+r) / 2
  // 分治递归
  merge_sort_c(A, p, q)
  merge_sort_c(A, q+1, r)
  // 将 A[p...q] 和 A[q+1...r] 合并为 A[p...r]
  merge(A[p...r], A[p...q], A[q+1...r])
}

分析プロセス:

1. Aと同じサイズの一時配列tmpを適用します[p ... r]

2. 2つのカーソルiとjを使用して、A [p ... q]とA [q + 1 ... r]の最初の要素をポイントします。

3.これら2つの要素A [i]とA [j]を比較します。A[i] <= A [j]の場合、A [i]を一時配列tmpに入れ、iを戻します。そうでない場合は、A [j]を配列tmpに入れ、jを後方にシフトします。

4. 1つの配列がすべて完成するまで上記のプロセスを繰り返し、要素を別の配列に順番に配置します。

5.最後に、一時配列tmpのデータを元の配列A [p…r]にコピーします...

安定性:安定した選別、

時間の複雑さ:

T(1)= C; n = 1の場合、一定レベルの実行時間が必要なだけなので、Cとして表されます。

T(n)= 2 * T(n / 2)+ n; n> 1

T(n) = 2*T(n/2) + n
     = 2*(2*T(n/4) + n/2) + n = 4*T(n/4) + 2*n
     = 4*(2*T(n/8) + n/4) + 2*n = 8*T(n/8) + 3*n
     = 8*(2*T(n/16) + n/8) + 3*n = 16*T(n/16) + 4*n
     ......
     = 2^k * T(n/2^k) + k * n
     ......

T(n)= 2 ^ kT(n / 2 ^ k)+ kn。

T(n / 2 ^ k)= T(1)、つまりn / 2 ^ k = 1の場合、k = log2nが得られます。上記の式にkの値を代入して、T(n)== Cn + nlog2nを取得します。大きなO表記を使用する場合、T(n)はO(nlogn)と等しくなります。

実行効率は、並べ替えられる元の配列の順序とは関係がないため、時間の複雑度は非常に安定しています。それが最良の場合、最悪の場合、または平均的な場合のいずれであっても、時間の複雑度はO(nlogn)です。

スペースの複雑さ:一時スペースがnの配列を開発する必要があるため、スペースの複雑度はO(n)であり、致命的な弱点です。

実現:

package main

import "fmt"

func main() {
	arr := []int{8, 9, 5, 7, 1, 2, 5, 7, 6, 3, 5, 4, 8, 1, 8, 5, 3, 5, 8, 4}
	tempArr := mergeSort(arr)
	fmt.Println(tempArr)
}

/**
归并排序(Merge sort,台湾译作:合并排序)是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用
分治思想,时间复杂度为:O(n*log(n))
*/

func mergeSort(arr []int) []int {
	if len(arr) < 2 {
		return arr
	}
	i := len(arr) / 2
	left := mergeSort(arr[0:i])
	right := mergeSort(arr[i:])
	tempArr := merge(left, right)
	return tempArr
}

func merge(left, right []int) []int {
	tempArr := make([]int, 0)
	m, n := 0, 0 // left和right的index位置
	l, r := len(left), len(right)
	for m < l && n < r {
		if left[m] > right[n] {
			tempArr = append(tempArr, right[n])
			n++
			continue
		}
		tempArr = append(tempArr, left[m])
		m++
	}
	tempArr = append(tempArr, right[n:]...) // 这里竟然没有报数组越界的异常?
	tempArr = append(tempArr, left[m:]...)
	return tempArr
}

 

公開された127元の記事 ウォン称賛24 ビュー130 000 +

おすすめ

転載: blog.csdn.net/Linzhongyilisha/article/details/100110826