算法流程:
归并排序主要分为两部分:
1、划分子区间
2、合并子区间
现在以 9,6,7,22,20,33,16,20 为例讲解上面两个过程:
第一步,划分子区间:每次递归的从中间把数据划分为左区间和右区间。原始区间为[start,end],start=0,end=[length-1],减一是因为数组的下标从0开始,本例中length=8,end=7.现在从中间元素划分,划分之后的左右区间分别为 [start,(end-start+1)/2+start],右区间为[(end-start+1)/2+start+1,end],本例中把start和end带入可以得到[0,7],划分后的左右子区间为[0,4],[5,7],然后分别对[start,end]=[0,4]和[start,end]=[5,7]重复上一步过程,直到每个子区间只有一个或者两个元素。整个分解过程为:
第二步,子区间划分好以后,分别对左右子区间进行排序,排好序之后,在递归的把左右子区间进行合并,整个过程如下图所示:
实现方法:
// letcode.cpp : 定义控制台应用程序的入口点。
//
#include"stdafx.h"
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<vector>
#include<algorithm>
using namespace std;
void merge(int *data, int start, int end, int*result)
{
int left_index = start;
int left_length = (end - start + 1) / 2 + 1;
int right_index = start + left_length;
int result_index = start;
while (left_index <start+left_length&&right_index < end + 1)
{
if (data[left_index] <= data[right_index])
result[result_index++] = data[left_index++];
if (data[left_index] > data[right_index])
result[result_index++] = data[right_index++];
}
while (left_index<start+left_length)
result[result_index++] = data[left_index++];
while (right_index<end + 1)
result[result_index++] = data[right_index++];
}
void merge_sort(int*data, int start, int end, int*result)
{
if (end - start == 1)
{
if (data[start] > data[end])
{
int temp = data[start];
data[start] = data[end];
data[end] = temp;
}
return;
}
else if (end - start == 0)
return;
else
{
//int length = end - start + 1;
merge_sort(data, start, (end - start + 1) / 2 + start, result);
merge_sort(data, (end - start + 1) / 2 + start + 1, end, result);
merge(data, start, end, result);
for (int i = start; i <= end; i++)
data[i] = result[i];
}
}
int main()
{
int data[] = { 9,6,7,22,20,33,16,20 };
const int length = 8;
int result[length];
cout << "Before sorted:" << endl;
for (int i = 0; i < length; ++i)
cout << data[i] << " ";
cout << endl;
cout << "After sorted:" << endl;
merge_sort(data, 0, length - 1, result);
for (int i = 0; i < length; ++i)
cout << data[i] << " ";
cout << endl;
system("pause");
return 0;
}