经典排序算法(快排和归并)

快速排序

快速排序的步骤:

1.准备工作,建立数组(尽量大)用来存放原始数据。

2.确定分界点X,一般确定为两端和中间(数组的)。

3.调整区间,使得该数组被分为两部分(一部分大于等于X,一部分小于等于X)

核心步骤:建立双指针,一个指针指向第一个数的前一个,另一个指向最后一个元素的后一个,便于我们书写,让两个指针不断比较移动(当指针停止时,交换当时前指针上的数)使其可以继续移动,最后数组被分为两部分,一部分小于X,一部分大于X。

4.递归不断缩小区间,使得两端变成有序的数组。

代码

#include<iostream>
using namespace std;
const int N = 1e6 + 10;
int n;
int a[N];
void quick_sort(int a[], int l, int r)
{
	if (l >= r)return;//如果递归到只有一个或者没有元素的时候,停止

	int i = l - 1, j = r + 1, x = a[(l + r) / 2];//i取初始数组的前一位,j取最后一位的后一位,便于操作。
	//x为标准数,将区间一分为二
	while (i < j)
	{
		while (a[++i] < x);//让i前面的数字都小于x
		while (a[--j] > x);//让j后面的数字都大于x
		if (i < j)swap(a[i], a[j]);//当两个指针停止运行的时候,说明当前的两个数字不符合要求(a[i]>x,a[j]<x])
		//那么交换两个数字使其满足要求
	}

	quick_sort(a, l, j);//递归处理,使得数组变得有序
	quick_sort(a, j + 1, r);
}
int main()
{
	cin >> n;//输入需要排序的个数
	for (int i = 0; i < n; i++)cin >> a[i];//输入数组

	quick_sort(a, 0, n - 1);

	for (int i = 0; i < n; i++)cout << a[i] << " ";//输出数组
	return 0;
}

归并排序:

归并排序的基本步骤:

1.准备工作,建立两个数组,一个数组用来存放原始数据,另一个数组用来存储排序后的数组

2.将原数组一分为二(选取分界点,一般选择中间为分界点),并对两部分的数组进行递归处理,使得两部分的数组都变得有序

3.经过步骤二,两部分的数组都是有序的(从小到大)

核心思想:两部分的数组从前到后依次比较(双指针),选择出当前最小的数,并将此数存放起来(第二个数组),最后会出现一个部分中的数全部用完,另一个部分会剩余一部分(此部分数都大于前面已排序的数),因此将这部分的数直接加入到第二个数组即可。

4.将第二个数组中的数全部放到第一个原始数组中去(简单的循环)

代码:

#include<iostream>

using namespace std;
const int N = 1e6 + 10;
int n;
int a[N], b[N];//一个用来放原始数据,另一个放排序后的数组
void merge_sort(int a[], int l, int r)
{
	if (l >= r)return;//边界问题,当数组只有一个数或者没有数的时候,直接返回

	int mid = (l + r) / 2;//取分界点,一般为数组中间
	merge_sort(a, l, mid);//递归处理两部分数使其变的有序
	merge_sort(a, mid + 1, r);

	int i = l, j = mid + 1, k = 0;//双指针,分别指向两部分的第一个数
	while (i <= mid && j <= r)//当一部分的数比较完毕的时候直接退出
	{
		if (a[i] < a[j])b[k++] = a[i++];
		else b[k++] = a[j++];
	}

	while (i <= mid)b[k++] = a[i++];//推出上面的排序后,会有一部分的数未使用(大于已排序的数),将其加入到排序的数组
	while (j <= r)b[k++] = a[j++];

	for (int i = l, j = 0; i <= r; i++, j++)a[i] = b[j];//将原始数据排序好
}
int main()
{
	cin >> n;

	for (int i = 0; i < n; i++)cin >> a[i];
	merge_sort(a, 0, n-1);

	for (int i = 0; i < n; i++)cout << a[i] << " ";
	return 0;
}

这些算法主要是为了了解分治的思想,将大问题化小,从而逐个击破。

分治算法介绍

分治法的设计思想是:将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之。

   分治策略是:对于一个规模为n的问题,若该问题可以容易地解决(比如说规模n较小)则直接解决,否则将其分解为k个规模较小的子问题,这些子问题互相独立且与原问题形式相同,递归地解这些子问题,然后将各子问题的解合并得到原问题的解。这种算法设计策略叫做分治法。

   如果原问题可分割成k个子问题,1<k≤n,且这些子问题都可解并可利用这些子问题的解求出原问题的解,那么这种分治法就是可行的。由分治法产生的子问题往往是原问题的较小模式,这就为使用递归技术提供了方便。在这种情况下,反复应用分治手段,可以使子问题与原问题类型一致而其规模却不断缩小,最终使子问题缩小到很容易直接求出其解。这自然导致递归过程的产生。分治与递归像一对孪生兄弟,经常同时应用在算法设计之中,并由此产生许多高效算法。

sort 太好用了!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值