分治法
-
定义:使用递归的技巧,可以将一个问题拆分成两个或更多较小的局部问题,利用递归函数求出每个局部问题的劫,然后再将结果整合,最终解决问题,这种编程手法称为分治法。
-
分治法的核心是将问题分割、拆解为同类的小问题(神似套娃),再进行整合。但是在设计时必须要留有终点。
高等排序
当数据庞大或在一些体积庞大的数组面前,冒泡排序(复杂度高达o(n^2))的初等排序就失去了实用价值,通常在竞赛中会出现超时。由此就会用到高等排序。其中,包括归并排序、快速排序和计数排序(桶排序)。
归并排序
算法核心:
1.将给定的包含n个元素的局部数组“分割”成两个局部数组,每个数组各包含n/2个元素。
2.对两个局部数组分别执行mergesort排序。
3.通过merge将两个以排序完毕的局部数组整合为一个数组。
实例:ALDS1_5_B:Merge Sort
//输入一串数字,排序后输出排序完毕的数字,并输出比较运算的次数。
#include<stdio.h>
#include<iostream>
using namespace std;
const int MAX = 500005;
const int SENRINRL = 200000000;
int cnt;
int l[MAX/2+2], r[MAX / 2 + 2];
void merge(int s[], int n, int left, int mid, int right)
{
int n1 = mid - left;
int n2 = right - mid;
for(int i = 0; i < n1; i++) l[i] = s[left+i];
for(int i = 0; i < n2; i++) r[i] = s[mid+i];
l[n1] = r[n2] = SENRINRL;
int i = 0, j = 0;
for(int k = left; k < right; k++)
{
cnt++;
if(l[i] <= r[j])
s[k] = l[i++];
else
s[k] = r[j++];
}
}
void mergeSort(int s[], int n, int left, int right)
{
if(left+1 < right)
{
int mid = (right + left) / 2;
mergeSort(s, n, left, mid);
mergeSort(s, n, mid, right);
merge(s, n, left, mid, right);
}
}
int main(void)
{
int n;
int s[MAX];
cin >> n;
for(int i = 0; i < n; i++)
{
cin >> s[i];
}
mergeSort(s, n, 0, n);
for(int i = 0; i < n; i++)
{
if(i != 0)
cout << " ";
cout << s[i];
}
cout << endl;
cout << cnt << endl;
return 0;
}
快速排序
快速排序是基于分治法的算法。
算法核心:
1.通过分割直接将对象局部数组分割为前后两个局部数组。
2.对前半部分的局部数组执行quickSort.
3.对后半部分的局部数组执行quickSort.
注意:
1.快速排序在分割的过程中会交换不相邻的元素,因此属于不稳定的排序算法。而且,与归并排序不同,快排不必额外占用内存。
2.在C++STL 标准库中有sort函数,基于快速排序,但与快排相同,是不稳定的排序算法。若需要稳定的排序算法,可以蚕蛹以归并排序为基础的stable_sort。但就日常竞赛做题而言,多用sort.
3.sort详情:
(1)sort函数包含在#include<algorithm>头文件中;
(2)sort有三个参数:sort(start, end, 排序方法)
第一个参数是要排序的数组的起始地址;第二个参数是要排序数组的最后一位要排序的地址;第三个参数是排序方法,默认为由小到大。
快排实例(C语言实现):
#include<stdio.h>
void Quicksort(int a[], int s, int e)
{
int temp;
if(s >= e)
return;
int k = a[s];
int i = s, j = e;
while(i != j){
while(j > i && a[j] >= k)
j--;
temp = a[i];
a[i] = a[j];
a[j] = temp;
while(i < j && a[i] <= k)
i++;
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
Quicksort(a, s, i-1);
Quicksort(a, i+1, e);
}
int a[] = {1, 51, 4, 87, 55, 66, 12, 35};
int main(void)
{
int i;
int size = sizeof(a) / sizeof(int);
Quicksort(a, 0, size-1);
for( i = 0; i < size; i++){
printf("%d ", a[i]);
}
return 0;
}