归并排序是利用归并的思想实现的排序方法,该算法采用经典的分治(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()
}