AcWing算法基础课_第一章-基础算法(一)

目录


一、快速排序

主要思想:分治

区间[l,r]

1.确定分界点x:左边界q[l]、中间值q[(l+r)/2]、右边界q[r]、随机数

2.划分区间:

3.递归处理左右两段

划分区间暴力做法:

优法:双指针法

#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
using namespace std;
const int N = 1e6 + 10;
int n;
int q[N];
void quick_sort(int q[], int l, int r)
{
	if (l >= r)return;//区间内没有数或只有1个数
	int x = q[l], i = l - 1, j = r + 1;
	while (i < j)
	{
		do i++; while (q[i] < x);//i++直到q[i]>=x
		//i从左向右移动 如果数字小于x(处于正确位置)
		//那么就继续移动
		//如果遇到了大于等于x的数 i指针就停下

		do j--; while (q[j] > x);//j--直到q[i]<=x
		//j从右向左移动 如果数字大于x(处于正确位置)
		//那么就继续移动
		//如果遇到了小于等于x的数 j指针就停下

		//i和j指向的数字位置都不对 交换一下
		if (i < j) swap(q[i], q[j]);

		//i左边的数字始终都小于等于x;j右边的数字始终大于等于x
		//直到i和j相遇时
	}
	quick_sort(q, l, j);//排枢轴左边的元素
	quick_sort(q, j + 1, r);//排枢轴右边的元素
}
int main()
{
	scanf("%d", &n);
	for (int i = 0; i < n; i++)scanf("%d", &q[i]);
	quick_sort(q, 0, n - 1);
	for (int i = 0; i < n; i++)printf("%d ", q[i]);
	return 0;
}

C语言:

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>

void quick_sort(int a[], int l, int r)
{
	if (l >= r) return ;
	int x = a[l], i = l - 1, j = r + 1;
	while (i < j)
	{
		
	//	while (a[++i] < x);
	//	while (a[--j] > x);
		do i++; while (a[i] < x);
		do j--; while (a[j] > x);
			if (i < j) {
				int t = a[i];
				a[i] = a[j];
				a[j] = t;
		}
	}
	quick_sort(a, l, j);
	quick_sort(a, j + 1, r);

}

int main()
{
	int n;
	scanf("%d", &n);
	int* a = (int*)malloc(n * sizeof(int));
	for (int i = 0; i < n; i++)
	{
		scanf("%d", &a[i]);
	}
	quick_sort(a, 0, n - 1);
	for (int i = 0; i < n; i++) {
		printf("%d ", a[i]);
	}

	free(a);
	return 0;

}

举例:

比如1 6 4 5 2排序,一开始把x定成1整个循环结束不改变顺序,1就是正确位置,接着递归后面

6 4 5 2

二、归并排序

思想:分治

1.确定分界点:mid=(l+r)/2

2.递归排序:left right 的内部元素

3.归并:将 left和 right 这两个有序数组合二为一

方法:双指针(1和2)

1和2分别指向left和right两个数组的第一个元素,两数进行比较,小的数放在新数组的第一个位置,然后指针后移,其内的第二个元素再与另一个数组比较大小....直到一个指针移动到一个数组的再将另一个数组后续元素接到新数组里,最后将tem数组中的元素拷贝回原先的数组q中,完成归并操作。

代码实现:

#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
using namespace std;

const int N = 1e5+10;
int n;
int q[N],tem[N];


void merge_sort(int q[], int l, int r)
{
	if (l >= r) return;
	//确定分界点
	int mid = (l + r) / 2;

	merge_sort(q, l, mid), merge_sort(q, mid + 1, r);
	//对数组左半部分和右半部分分别进行排序

	//归并
	int k = 0, i = l, j = mid + 1;
	//k表示合并以后的元素个数;i指针指向第一个有序数组的起点,j指向另一个数组起点

	//合并两个数组
	while (i <= mid && j <= r)
		if (q[i] <= q[j]) tem[k++] = q[i++];
	    else tem[k++] = q[j++];
	// 上面循环基于两个指针都没有越界
	//还要注意当某一个指针到达边界之后 另一个数组的元素还要添加
	 while (i <= mid) tem[k++] = q[i++];
	while (j <= r)tem[k++] = q[j++];

	for (i = l, j = 0; i <= r; i++,j++)q[i] = tem[j];




}
int main()
{
	scanf("%d", &n);
	for (int i = 0; i < n; i++)scanf("%d", &q[i]);
	merge_sort(q, 0, n - 1);//整个输入的数组
	for (int i = 0; i < n; i++)printf("%d ", q[i]);

	return 0;
}

在这个过程中,先将数组分成左右两部分,然后对左右两部分分别进行递归调用 merge_sort 函数进行排序,直到左右两部分各剩下一个元素或没有元素为止。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值