빠른 정렬 및 병합 정렬 알고리즘의 템플릿 및 애플리케이션

빠른 정렬 및 병합 정렬 알고리즘의 템플릿 및 애플리케이션

1. 퀵 정렬

핵심 아이디어: 시퀀스를 두 부분으로 나누고 왼쪽 절반의 모든 숫자는 오른쪽 절반의 모든 숫자보다 작거나 같거나 크거나 같습니다. 왼쪽과 오른쪽 부분을 재귀적으로 처리합니다.

특정 단계: 여기서 q는 배열이고, l는 배열 왼쪽 끝점의 첨자이며, r는 배열 오른쪽 끝점의 첨자입니다.

  • 컷오프 포인트 결정q[(l+r)>>1] , 즉,q[(l+r)/2]
  • 이중 포인터를 사용하여 왼쪽 및 오른쪽 간격을 조정하여 왼쪽 간격의 데이터가 오른쪽 간격의 데이터보다 작거나 같도록(오름차순) 왼쪽 간격의 데이터를 올바른 간격의 데이터(내림차순)
  • 왼쪽 및 오른쪽 간격의 재귀 처리[l,j][j+1,r]

알고리즘 예시:

#include<iostream>
using namespace std;

const int N = 1e6 + 10;
int q[N];

void quick_sort(int* q, int l, int r)//快排模板
{
    
    
	if (l >= r) return;//必须 >=
	int x = q[l + r >> 1], i = l - 1, j = r + 1;
	while (i < j)
	{
    
    
		while (q[++i] < x);
		while (q[--j] > x);
		if (i < j) swap(q[i], q[j]);
	}
	quick_sort(q, l, j);
	quick_sort(q, j + 1, r);
}

int main()
{
    
    
	int n;
	cin >> n;
	for (int i = 0; i < n; ++i) cin >> q[i];
	quick_sort(q, 0, n - 1);
	for (int i = 0; i < n; ++i) cout << q[i] << " ";
}

2. 빠른 선택

소개: 빠른 선택 알고리즘은 빠른 정렬을 기반으로 하는 시간 복잡도가 O(n)인 알고리즘으로, 시퀀스에서 k번째로 작은 수를 찾는 기능을 합니다.

단계:

  • 일반적으로 퀵 정렬 알고리즘과 유사합니다.
  • 차이점은 k가 왼쪽 절반 간격의 길이보다 작거나 같으면 왼쪽 절반을 재귀적으로 처리한다는 것입니다.
  • 그렇지 않으면 오른쪽 절반을 재귀적으로 처리합니다.

알고리즘 예시:

const int N = 100010;
int q[N];

int quick_sort(int l, int r, int k)
{
    
    
	if (l == r) return q[l]; //可以以==,也可以>=
	int x = q[l + r >> 1], i = l - 1, j = r + 1;
	while (i < j) {
    
    
		while (q[++i] < x);
		while (q[--j] > x);
		if (i < j) swap(q[i], q[j]);
	}
	int sl = j - l + 1;//sl为左区间元素的个数
	if (k <= sl) return quick_sort(l, j, k);
	return quick_sort(j + 1, r, k - sl);
}

int main()
{
    
    
	int n, k;
	cin >> n >> k;
	for (int i = 0; i < n; ++i) cin >> q[i];
	cout << quick_sort(0, n - 1, k) <<endl;
}

3. 병합 정렬

핵심 아이디어: 두 개의 정렬된 동일한 시퀀스를 하나의 정렬된 시퀀스로 병합

구체적인 단계:

  • 컷오프 포인트를 결정하고 간격을 [l,r]로 나눕니다.[l,mid][mid+1,r]
  • 왼쪽 및 오른쪽 간격 의 재귀 처리[l,mid][mid+1,r]
  • 병합 , 정렬된 두 범위를 하나의 정렬된 범위로 병합

알고리즘 예시:

const int N = 1e6 + 10;
int q[N], t[N];

void merge_sort(int* q, int l, int r)//归并排序模板
{
    
    
	if (l >= r) return;
	int mid = l + r >> 1;
	merge_sort(q, l, mid);
	merge_sort(q, mid + 1, r);
	int k = 0, i = l, j = mid + 1;
	while (i <= mid && j <= r)
	{
    
    
		if (q[i] <= q[j]) t[k++] = q[i++];
		else t[k++] = q[j++];
	}
	while (i <= mid) t[k++] = q[i++];
	while (j <= r) t[k++] = q[j++];
	for (int i = l, j = 0; i <= r; ++i, ++j) q[i] = t[j];
}

int main()
{
    
    
	int n;
	cin >> n;
	for (int i = 0; i < n; ++i) cin >> q[i];
	merge_sort(q, 0, n - 1);
	for (int i = 0; i < n; ++i) cout << q[i] << " ";
}

넷째, 역순 쌍의 수

역쌍 정의: 두 개의 숫자, 전자가 후자보다 큰 경우 이 두 숫자를 역쌍이라고 합니다.

간략한 설명: 시퀀스에서 역방향 쌍의 수 찾기

알고리즘 예시:

typedef long long ll;//结果可能大于int的范围,函数返回值用long long类型
const int N = 100010;
int q[N], t[N];

ll merge_sort(int l, int r)
{
    
    
	if (l >= r) return 0;
	int mid = l + r >> 1;
	ll ret = merge_sort(l, mid) + merge_sort(mid + 1, r);
	int k = 0, i = l, j = mid + 1;
	while (i <= mid && j <= r) {
    
    
		if (q[i] <= q[j]) t[k++] = q[i++];
		else {
    
    
			t[k++] = q[j++];
			ret += mid - i + 1;
		}
	}
	while (i <= mid) t[k++] = q[i++];
	while (j <= r) t[k++] = q[j++];
	for (int i = l, j = 0; i <= r; ++i, ++j) q[i] = t[j];
	return ret;
}
int main()
{
    
    
	int n;
	cin >> n;
	for (int i = 0; i < n; ++i) cin >> q[i];
	cout << merge_sort(0, n - 1) << endl;
}

추천

출처blog.csdn.net/qq_52324409/article/details/122480940