Ordenar fusión
Primero divida la matriz del medio en dos partes, y luego ordene las dos partes por separado, y luego combine las dos partes en orden, de modo que toda la matriz esté ordenada
Divide la mente, divide y gobierna.
Dividir y conquistar es un pensamiento para resolver problemas, la recursividad es una habilidad de programación
Fórmula recursiva:
merge_sort (p ... r) = merge (merge_sort (p ... q), merge_sort (q + 1 ... r))
Condición de terminación: p> = r ya no necesita continuar la descomposición
Pseudocódigo:
// 归并排序算法, 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])
}
Proceso de análisis:
1. Solicite una matriz temporal tmp con el mismo tamaño que A [p ... r].
2. Usamos dos cursores i y j para señalar el primer elemento de A [p ... q] y A [q + 1 ... r], respectivamente.
3. Compare estos dos elementos A [i] y A [j], si A [i] <= A [j], colocamos A [i] en la matriz temporal tmp, y me desplazamos por uno, De lo contrario, coloque A [j] en la matriz tmp y desplace j hacia atrás.
4. Repita el proceso anterior hasta que una matriz esté terminada, y luego coloque los elementos en otra matriz a su vez.
5. Finalmente, copie los datos en la matriz temporal tmp a la matriz original A [p ... r] ...
Estabilidad : clasificación estable,
Complejidad del tiempo:
T (1) = C; cuando n = 1, solo se necesita tiempo de ejecución de nivel constante, por lo que se expresa como 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。
Cuando T (n / 2 ^ k) = T (1), es decir n / 2 ^ k = 1, obtenemos k = log2n. Sustituimos el valor de k en la fórmula anterior para obtener T (n) == Cn + nlog2n. Si usamos la notación O grande, T (n) es igual a O (nlogn) .
La eficiencia de ejecución no tiene nada que ver con el orden de la matriz original que se va a ordenar, por lo que su complejidad temporal es muy estable. Ya sea el mejor caso, el peor caso o el caso promedio, la complejidad temporal es O (nlogn).
Complejidad del espacio : es necesario abrir una matriz con un espacio temporal de n, por lo que la complejidad del espacio es O (n) , una debilidad fatal.
Darse cuenta:
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
}