分而治之
一个输入规模较大不容易直接求解的问题,如果可以分成多个类型相同的规模相对较小的问题,且能够找到适当的方法将这些小问题的解合并成整个问题的解时,那么此时就可以考虑采用分治法。
二分查找(Binary Search)
初始条件:输入的数列需有序。
返回值:目标存在返回下标,否则返回0
int _BIN_SRCH( int *a, int len, int target )
{
// "a": 存储有序数列的数组
// "len": 数列的长度
// "target": 查找目标
int low, high, mid;
low = 1, high = len;
while( low <= len ) {
mid = (low+high)/2;
if( *(a+mid) == target ) return mid;
else if( *(a+mid) < target ) low = mid + 1;
else high = mid - 1;
}
return 0;
}
求最大最小值
初始条件:需给出整数数组,查找范围。
此函数仅仅是联系,在实际运用中不论是时间还是空间都不会优于最简单的遍历法。
算法思想:在给定长度n的整数序列中,查找最大和最小值。可以将这一个规模为n的问题分解成,分别在序列(1,n/2)和序列(n/2+1,n)中查找最大和最小值两个规模为n/2的问题,再讲计算的结果进行比较得到整个问题的答案。
int _BIN_FIND_MAX_MIN( int *a, int i, int j, int *max, int *min )
{
// 数组a可无序
// i <= j
// 查询的结果存入max、min中。
int max1,min1;
int max2,min2;
int mid;
if( i == j ) {
*max = *(a+i);
*min = *(a+i);
}
else if( i == j-1 ) {
if( *(a+i) <= *(a+j) ) {
*min = *(a+i);
*max = *(a+j);
}
else {
*min = *(a+j);
*max = *(a+i);
}
}
else {
mid = (i+j)/2;
_BIN_FIND_MAX_MIN(a,i,mid,&max1,&min1);
_BIN_FIND_MAX_MIN(a,mid+1,j,&max2,&min2);
if( max1 <= max2 ) *max = max2;
else *max = max1;
if( min1 <= min2 ) *min = min1;
else *min = min2;
}
return 0;
}
归并排序(Merge Sort)
算法思想:将规模为n的整形数组从中分成两个规模为n/2的数组,分别对这两个数组进行排序,再将两个有序的数组合并。
此算法默认升序排序
int _MERGE_SORT( int *a, int low, int high )
{
// "a": 待排序数组首地址
// "low": 待排序部分开始下标
// "high": 待排序部分结束下标
int mid;
if( low < high ) {
mid = (low + high)/2;
_MERGE_SORT(a,low,mid);
_MERGE_SORT(a,mid+1,high);
// 将数组a中有序部分(low,mid)和(mid+1,high)合并
_MERGE(a,low,mid,high);
}
return 0;
}
快速排序(Quick Sort)
算法思想:首先在数组a中确定一个关键元素,然后将比其小的值都放在左边,比其大的值都放在右边(升序排序),这样就确定的该关键元素的位置。之后再依此方法分别处理余下的左右两部分,以此类推即可完成排序。
int _QUICK_SORT( int *a, int s, int e )
{
// "a": 整数数组
// "s": 待排序部分开始下标
// "e": 待排序部分结束下标
int p;
if( s < e ) {
p = _PARTITION(a,s,e); // 实现分类,返回关键字下标
_QUICK_SORT(a,s,p-1);
_QUICK_SORT(a,p+1,e);
}
return 0;
}
int _PARTITION( int *a, int s, int e )
{
// 以下标"s"对应的值为关键值,进行分类
*(a+0) = *(a+s);
while(1) {
while( *(a+0) > *(a+s) ) s++;
while( *(a+0) < *(a+e) ) e--;
if( s < e ) SWAP(a+s,a+e);
else break;
}
return e;
}
基于快速排序的选择算法
算法目的:找出数组中第P小的数
算法思想:根据快速排序的特点,即每一次Loop可以确定一个值m的位置,同时能够确定m所对应的下标Pm所表示的意义就是“m在该数组中是第Pm小的数”。因此,若Pm
int _SELECT( int *a, int s, int e, int target )
{
int p;
if( s < e ) {
p = _PARTITION(a,s,e); // 前文已实现
if( p == target ) return *(a+p);
else if( p < target ) return _SELECT(a,p+1,e,target);
else return _SELECT(a,s,p-1,target);
}
return 0;
}