Algorithm理解用例:分治法

分而治之

一个输入规模较大不容易直接求解的问题,如果可以分成多个类型相同的规模相对较小的问题,且能够找到适当的方法将这些小问题的解合并成整个问题的解时,那么此时就可以考虑采用分治法。

二分查找(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;
}
点赞