归并排序(简单讲解)

发布于:2025-08-03 ⋅ 阅读:(13) ⋅ 点赞:(0)

排序有许多种方法,其中最为简单的sort排序与冒泡排序,但是在一些需要排序的题目中这两个方法就不好用了。

例如洛谷P1908需要用到归并排序,今天我们来简单讲解一下这个排序方法。

首先我们需要明白,归并排序其实和二分有些相似的地方,具体如图

需要依次将一个数组分成单个后,比较大小,再次合并成为一个新的且排好顺序的数组

那么我们要攻克的难点为

1 将数组依次分开

2 排序

3 合并

分开时要用到二分的思想,当左端点小于右端点时进行分割,直到将整个数组分成单个数字存在,随后进行排序与合并

if(left<right)
	{
		int mid=(left+right)>>1;
		mmsort(arr,add,left,mid);
		mmsort(arr,add,mid+1,right);
		gb(arr,add,left,mid,right);
	}

这里我将排序与合并写在了一起,先存入左端点与右端点,方便后续将数据存入新数组,随后在循环中将此时要判断数据放入新数组中,最后将还没有存完的数组一起放在新数组的尾端,最后将新数组中的数据覆盖原数组

int l=left,r=mid+1;
	int pp=left;
	while(l<=mid&&r<=right)
	{
		if(arr[l]<arr[r])
		{
			add[pp++]=arr[l++];
		}
		else
		{
			add[pp++]=arr[r++];
		}
	}
	while(l<=mid)
	{
		add[pp++]=arr[l++];
	}
	while(r<=right)
	{
		add[pp++]=arr[r++];
	}
	while(left<=right)
	{
		arr[left]=add[left];
		left++;
	}

完整代码如下:

#include<bits/stdc++.h>
using namespace std;
int n;
int arr[200000];
void gb(int arr[],int add[],int left,int mid,int right)
{
	int l=left,r=mid+1;
	int pp=left;
	while(l<=mid&&r<=right)
	{
		if(arr[l]<arr[r])
		{
			add[pp++]=arr[l++];
		}
		else
		{
			add[pp++]=arr[r++];
		}
	}
	while(l<=mid)
	{
		add[pp++]=arr[l++];
	}
	while(r<=right)
	{
		add[pp++]=arr[r++];
	}
	while(left<=right)
	{
		arr[left]=add[left];
		left++;
	}
}
void mmsort(int arr[],int add[],int left,int right)
{
	if(left<right)
	{
		int mid=(left+right)>>1;
		mmsort(arr,add,left,mid);
		mmsort(arr,add,mid+1,right);
		gb(arr,add,left,mid,right);
	}
}
void msort(int arr[],int n)
{
	int add[n+10];
	mmsort(arr,add,0,n-1);
}
int main()
{
	cin>>n;
	for(int i=0;i<n;i++)
	{
		cin>>arr[i];
	}
	msort(arr,n);
	for(int i=0;i<n;i++)
	{
		cout<<arr[i]<<" ";
	}
	return 0;
 }