Merge Sort - 归并排序
核心:归并排序是采用分治法的一个非常典型的应用。
归并排序的分析- 归并排序的思想就是先递归分解数组,再合并数组。
- 将数组分解最小之后,然后合并两个有序数组,基本思路是比较两个数组的最前面的数,谁小就先取谁,取后相应指针就往后移一位。然后再比较,直至一个数组为空,最后把另一个数组的剩余部分复制过来即可。
- 先写出归并排序递推公式
递推公式:
merge_sort(p…r) = merge(merge_sort(p…q), merge_sort(q+1…r))
终止条件:
p >= r 不用再继续分解
时间复杂度
- 最优时间复杂度:O(nlogn)
- 最坏时间复杂度:O(nlogn)
- 稳定性:稳定
- Python代码实现
"""
归并排序是采用分治法的一个非常典型的应用。归并排序的思想就是先递归分解数组,再合并数组。
最好时间复杂度:O(nlogn)
最坏时间复杂度:O(nlogn)
稳定性:稳定
"""
class Sort(object):
def mergeSort(self, alist):
n = len(alist)
if n <= 1:
return alist
mid = n // 2
# 二分分解
leftList = self.mergeSort(alist[:mid])
rightList = self.mergeSort(alist[mid:])
# 合并
return self._merge(leftList, rightList)
def _merge(self, leftList, rightList):
"""
合并操作,将两个有序列表leftList和rightList合并成一个大的有序列表
"""
l = r = 0
tempList = []
while l < len(leftList) and r < len(rightList):
if leftList[l] <= rightList[r]:
tempList.append(leftList[l])
l += 1
else:
tempList.append(rightList[r])
r += 1
tempList += leftList[l:]
tempList += rightList[r:]
return tempList
if __name__ == "__main__":
alist = [6, 5, 3, 1, 4, 7, 2, 4]
print(alist)
mergeSort = Sort()
sortAlist = mergeSort.mergeSort(alist)
print(sortAlist)
# 结果
[6, 5, 3, 1, 4, 7, 2, 4]
[1, 2, 3, 4, 4, 5, 6, 7]
- Java代码实现
import java.util.Arrays;
public class MergeSort{
private static void mergeSort(int[] alist, int l, int r){
if(l == r) {
return;
}
int mid = (r - l) / 2 + l;
mergeSort(alist, l, mid);
mergeSort(alist, mid + 1, r);
merge(alist, l, mid, r);
}
private static void merge(int[] alist, int l, int mid, int r){
int[] tempList = new int[r - l + 1];
int i = l, j = mid + 1, k = 0;
while(i <= mid && j <= r){
if (alist[i] <= alist[j]) {
tempList[k++] = alist[i++];
} else {
tempList[k++] = alist[j++];
}
}
while (i <= mid) {
tempList[k++] = alist[i++];
}
while (j <= r) {
tempList[k++] = alist[j++];
}
//把排好序的部分复制回原数组
for (int a : tempList) {
alist[l++] = a;
}
}
public static void main(String[] args) {
int[] alist = {100, 5, 3, 9, 8, 7, 2, 4, 15};
mergeSort(alist, 0, alist.length - 1);
System.out.println(Arrays.toString(alist));
}
}
# 结果
[2, 3, 4, 5, 7, 8, 9, 15, 100]
- C++代码实现
#include <iostream>
using namespace std;
void merge(int alist[], int l, int mid, int r){
int n = r - l + 1;
int* tempList = new int[n];
int i = l, j = mid + 1, k = 0;
while(i <= mid && j <= r){
if (alist[i] <= alist[j]) {
tempList[k++] = alist[i++];
} else {
tempList[k++] = alist[j++];
}
}
while (i <= mid) {
tempList[k++] = alist[i++];
}
while (j <= r) {
tempList[k++] = alist[j++];
}
// 把已排序的数组复制回原数组
for (int i = 0; i < n; i++) {
alist[l++] = tempList[i];
}
delete[] tempList;
}
void mergeSort(int alist[], int l, int r){
if (l == r) {
return;
}
int mid = (l + r) / 2;
// 分解
mergeSort(alist, l, mid);
mergeSort(alist, mid + 1, r);
// 合并
merge(alist, l, mid, r);
}
int main(){
int alist[] = {100, 5, 3, 9, 8, 7, 2, 4, 15};
int size = 9;
mergeSort(alist, 0, size - 1);
for (int i = 0; i < size; i++) {
std::cout << alist[i] << " ";
}
return 0;
}
# 结果
2 3 4 5 7 8 9 15 100
- Go代码实现
package main
import "fmt"
// 定义一个类
type MergeSort struct {
}
// 提供两个对外的接口
// 本质上就是对外提供两个公有方法
func (m * MergeSort)Sort(alist []int) []int {
n := len(alist)
if n <= 1 {
return alist
}
mid := n / 2
leftList := m.Sort(alist[:mid])
rightList := m.Sort(alist[mid:])
return m.merge(leftList, rightList)
}
func (m *MergeSort)merge(leftList []int, rightList []int) []int {
// 合并操作,将两个有序列表leftList和rightList合并成一个大的有序列表
l := 0
r := 0
// tempList := make([]int, 0)
var tempList []int
for l < len(leftList) && r < len(rightList) {
if leftList[l] <= rightList[r] {
tempList = append(tempList, leftList[l])
l++
} else {
tempList = append(tempList, rightList[r])
r++
}
}
tempList = append(tempList, leftList[l:]...)
tempList = append(tempList, rightList[r:]...)
return tempList
}
func main() {
a := []int{1, 5}
b := []int{3, 4}
c := append(a, b...)
fmt.Println(c)
alist := []int{6, 5, 3, 1, 4, 7, 2, 4}
sort := MergeSort{}
fmt.Println(sort.Sort(alist))
}
// 结果
[1 5 3 4]
[1 2 3 4 4 5 6 7]
参考文献
- 《数据结构与算法之美》
网友评论