Algorithm MergeSort归并排序

Reference:

归并排序_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili

其实有时候算法真正实现出来了再去看,也没当初自己觉得的那么难。
讲解用的C++,底下有用C实现了一下,其实没差。
具体的内容看顶部的视频,讲的很细。
归并排序名字已经说明了内涵,归指递归,将问题的规模缩小到只有一个元素时去解决,并指合并,将小的数组有序交叉合并,最后就能得到排序好的数组。
同样地,其实现也是分两步,递归(mergeSort)和合并(merge)。
mergeSort部分

void mergeSort(int arr[],int L,int R)
{
	if(L==R) return ;//递归基,如果所取区间左右边界相同,则只有一个元素,必然有序
	int M=(L+R)/2;//不然就折半
	mergeSort(arr,L,M);//先排左边
	mergeSort(arr,M+1,R);//再排右边,不要重叠。
	//注意这里所取的中点M和merge的中点要对应,只能把中点放在左边。
	merge(arr,L,M,R);//合并两个分别有序的数组
}

merge部分
merge的功能是把一个数组按某一点拆成两个,再有序交叉合并。
比如1,4,2,3,5以2为分割点拆开,得到left[]={1,4,2},right[]={3,5},然后升序合并。
1比3小,所以第一个数是left的1.
然后4比3大,所以第二个数是right的3.
然后4比5小,所以第三个数是right的5.
此时right里的数已经用完了,就把left里剩下的数全部拷贝过去,把4,2拷贝过去
merge的结果就是1,3,5,4,2。
如果merge前的两个数组是有序的,那么merge完也是有序的。

void merge(int arr[],int L,int M,int R)
{
	int left_size=M-L+1;//同样注意中间的元素不要重复,这里取左边的长一些,右边的短一些
	int right_size=R-M;
	int i=0,j=0,k=L;
	int *left=new int[left_size];//创建两个辅助数组来存储分割前后的内容
	int *right=new int[right_size];
	while(i<left_size)
		left[i++]=arr[k++];//拷贝前面的数字到left
	while(j<right_size)
		right[j++]=arr[k++];//拷贝后面的数字到right
	i=j=0,k=L;
	while(i<left_size&&j<right_size)//在两个数组都没遍历完之前,交叉合并
	{
		if(left[i]<right[j])//左边小,就取左边的数
		{
			arr[k]=left[i];
			i++;k++;
		}
		else
		{
			arr[k]=right[j];
			j++;k++;
		}
	}
	if(i==left_size)//其中一个已经遍历完后,把另一个拷贝过去即可
		while(j<right_size)
			arr[k++]=right[j++];
	else
		while(i<left_size)
			arr[k++]=left[i++];
	delete []left;
	delete []right;
}

最后实现的接口:
void mergeSort(数组名,起始下标,终止下标);
测试代码:

#include <iostream>
using namespace std;
void printArray(int a[],int L,int R)
{
	while(L<=R)
		cout<<a[L++]<<' ';
	cout<<endl;
}

void merge(int arr[],int L,int M,int R)
{
	int left_size=M-L+1;
	int right_size=R-M;
	int i=0,j=0,k=L;
	int *left=new int[left_size];
	int *right=new int[right_size];
	
	while(i<left_size)
		left[i++]=arr[k++];
	while(j<right_size)
		right[j++]=arr[k++];
		
	i=j=0,k=L;
	while(i<left_size&&j<right_size)
	{
		if(left[i]<right[j])
			arr[k++]=left[i++];
		else
			arr[k++]=right[j++];
	}
	
	if(i==left_size)
		while(j<right_size)
			arr[k++]=right[j++];
	else
		while(i<left_size)
			arr[k++]=left[i++];
	delete []left;
	delete []right;
}

void mergeSort(int arr[],int L,int R)
{
	if(L==R) return ;
	int M=(L+R)/2;
	mergeSort(arr,L,M);
	mergeSort(arr,M+1,R);
	merge(arr,L,M,R);
}

int main(int argc, char const *argv[])
{
	int arr[]={12,11,10,9,8,7,6,5,4,3,2,1,0};
	mergeSort(arr,0,12);
	printArray(arr,0,12);
	return 0;
}

结果:

0 1 2 3 4 5 6 7 8 9 10 11 12

C语言实现

#include <stdio.h>
#include <stdlib.h>
void printArray(int [],int,int);
void merge(int [],int,int,int);
void mergeSort(int [],int,int);

int main(int argc, char const *argv[])
{
	int arr[]={12,11,10,9,8,7,6,5,4,3,2,1,0};
	mergeSort(arr,0,12);
	printArray(arr,0,12);
	return 0;
}

void printArray(int a[],int L,int R)
{
	while(L<=R)
		printf("%d%c",a[L++],L==R?'\n':' ');
}

void merge(int arr[],int L,int M,int R)
{
	int left_size=M-L+1;
	int right_size=R-M;
	int i=0,j=0,k=L;
	int *left=(int*)malloc(sizeof(int)*left_size);
	int *right=(int*)malloc(sizeof(int)*right_size);

	while(i<left_size)
		left[i++]=arr[k++];
	while(j<right_size)
		right[j++]=arr[k++];
		
	i=j=0,k=L;
	while(i<left_size&&j<right_size)
	{
		if(left[i]<right[j])
			arr[k++]=left[i++];
		else
			arr[k++]=right[j++];
	}
	
	if(i==left_size)
		while(j<right_size)
			arr[k++]=right[j++];
	else
		while(i<left_size)
			arr[k++]=left[i++];
	free(left);
	free(right);
}

void mergeSort(int arr[],int L,int R)
{
	if(L==R) return ;
	int M=(L+R)/2;
	mergeSort(arr,L,M);
	mergeSort(arr,M+1,R);
	merge(arr,L,M,R);
}

猜你喜欢

转载自blog.csdn.net/weixin_43873801/article/details/87001281