归并排序(Two Way Merge Sort)

归并排序是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略(分治法将问题(divide)成一些小的问题然后递归求解,而 治(conquer) 的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之)。

整个过程就是:

  • 对左边不断划分
  • 对右边不断划分
  • 合并

在这里插入图片描述
在这里插入图片描述

代码如下(含调试输出过程):

#include<iostream>
#include<bits/stdc++.h>
using namespace std;

vector<int> temp, res;
int n;
void merge(int left, int mid, int right){
    //[left, mid] [mid+1, right]
    cout<<"merge-left: ";
    for(int ii=left; ii<=mid; ii++){
        cout<<res[ii]<<" ";
    }
    cout<<endl;
    cout<<"merge-right: ";
    for(int jj=mid+1; jj<=right; jj++){
        cout<<res[jj]<<" ";
    }
    cout<<endl;
    int count = 0;
    int i=left, j=mid+1;
    while(i<=mid && j<=right){
        if(res[i]<=res[j]){
            temp[count++]=res[i++];
        }else{
            temp[count++]=res[j++];
        }
    }
    while(i<=mid){
        temp[count++]=res[i++];
    }
    while(j<=right){
        temp[count++]=res[j++];
    }
    cout<<"merge: ";
    for(int k=0; k<(right-left+1); k++){
        res[left+k]=temp[k];
        cout<<temp[k]<<" ";
    }
    cout<<endl;
}
void MergeSort(int left, int right){
    cout<<"divide: ";
    for(int i=left; i<=right; i++){
        cout<<res[i]<<" ";
    }
    cout<<endl;
    if(left == right){
        return;
    }
    int mid = (left + right)/2;
    //对左边不断的划分
    MergeSort(left, mid);
    //对右边不断的划分
    MergeSort(mid+1, right);
    //合并,从底层一步步合并
    merge(left, mid, right);
}
int main(){
    cin>>n;
    int tmp;
    
    for(int i=0;i<n;i++){
        cin>>tmp;
        res.push_back(tmp);
    }
    temp.resize(n,0);//给一个固定的长度,不然会越界
    //不要放在merge中开辟,有可能会超时
    //leetcode 912. 排序数组
    MergeSort(0,n-1);
    for(int i=0; i<n; i++){
        cout<<res[i]<<" ";
    }
    cout<<endl;
    return 0;
}

输入: 9 2 5 1 3 2 9 5 2 1

输出调试一下:

10
9 2 5 1 3 2 9 5 2 1
divide: 9 2 5 1 3 2 9 5 2 1 
divide: 9 2 5 1 3
divide: 9 2 5
divide: 9 2
divide: 9
divide: 2
merge-left: 9
merge-right: 2
merge: 2 9 
divide: 5
merge-left: 2 9
merge-right: 5
merge: 2 5 9
divide: 1 3
divide: 1
divide: 3
merge-left: 1
merge-right: 3
merge: 1 3
merge-left: 2 5 9
merge-right: 1 3 
merge: 1 2 3 5 9
divide: 2 9 5 2 1
divide: 2 9 5
divide: 2 9
divide: 2
divide: 9
merge-left: 2
merge-right: 9
merge: 2 9
divide: 5
merge-left: 2 9
merge-right: 5 
merge: 2 5 9
divide: 2 1
divide: 2
divide: 1
merge-left: 2
merge-right: 1
merge: 1 2
merge-left: 2 5 9
merge-right: 1 2
merge: 1 2 2 5 9
merge-left: 1 2 3 5 9
merge-right: 1 2 2 5 9
merge: 1 1 2 2 2 3 5 5 9 9
1 1 2 2 2 3 5 5 9 9

下面上一个纯净版的,没有调试的乱七八糟的代码:

#include<iostream>
#include<bits/stdc++.h>
using namespace std;

vector<int> temp, res;
int n;
void merge(int left, int mid, int right){
    //[left, mid] [mid+1, right]
    int count = 0;
    int i=left, j=mid+1;
    while(i<=mid && j<=right){
        if(res[i]<=res[j]){
            temp[count++]=res[i++];
        }else{
            temp[count++]=res[j++];
        }
    }
    while(i<=mid){
        temp[count++]=res[i++];
    }
    while(j<=right){
        temp[count++]=res[j++];
    }
    for(int k=0; k<(right-left+1); k++){
        res[left+k]=temp[k];
    }
}
void MergeSort(int left, int right){
    if(left == right){
        return;
    }
    int mid = (left + right)/2;
    //对左边不断的划分
    MergeSort(left, mid);
    //对右边不断的划分
    MergeSort(mid+1, right);
    //合并,从底层一步步合并
    merge(left, mid, right);
}
int main(){
    cin>>n;
    int tmp;
    
    for(int i=0;i<n;i++){
        cin>>tmp;
        res.push_back(tmp);
    }
    temp.resize(n,0);//给一个固定的长度,不然会越界
    //不要放在merge中开辟,有可能会超时
    //leetcode 912. 排序数组
    MergeSort(0,n-1);
    for(int i=0; i<n; i++){
        cout<<res[i]<<" ";
    }
    cout<<endl;
    return 0;
}

加个go语言代码哈,刚开始学这门语言

package main

import "fmt"

func Merge(res []int, left, mid, right int) {
	fmt.Println("merge-left: ", res[left:mid+1])
	fmt.Println("merge-right: ", res[mid+1:right+1])

	tmp := make([]int, 0)

	i, j := left, mid+1
	for i <= mid && j <= right {
		if res[i] <= res[j] {
			tmp = append(tmp, res[i])
			i++
		} else {
			tmp = append(tmp, res[j])
			j++
		}
	}

	for ; i <= mid; i++ {
		tmp = append(tmp, res[i])
	}
	for ; j <= right; j++ {
		tmp = append(tmp, res[j])
	}
	fmt.Printf("merge: ")
	for k := 0; k < (right - left + 1); k++ {
		res[left+k] = tmp[k]
		fmt.Printf("%v ", tmp[k])
	}
	fmt.Println()
}
func MergeSort(res []int, left, right int) {
	if left == right {
		return
	}
	mid := (left + right) / 2
	MergeSort(res, left, mid)
	MergeSort(res, mid+1, right)
	Merge(res, left, mid, right)
}
func main() {
	var n int
	fmt.Scan(&n)
	res := make([]int, 0)
	var temp int
	for i := 0; i < n; i++ {
		fmt.Scan(&temp)
		res = append(res, temp)
	}
	MergeSort(res, 0, n-1)
	for _, value := range res {
		fmt.Printf("%v ", value)
	}

	fmt.Println()
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值