【数据结构与算法分析】复习笔记(1)

    目前为止,PAT初级题目和题解已经全部发完了。 鼓掌!撒花!

    初级题目几乎不需要用到复杂的数据结构,只需要基础的编程知识和简单的逻辑就可以完成。按姥姥的话说,“排序就是最复杂的了”(原话不记得了,不过是这个意思)。为了完成PAT的填坑大业,为了在9月份的PAT甲级比赛中不被题虐名列前茅并被优秀公司免试录取出任CEO迎娶白富美走上人生巅峰,果断开始走上备考甲级的不归之路!

    甲级涉及的知识点比较多,要求的能力比较高,更需要一些稍微复杂一些的编程思想。参考biaobiaoqi前辈的文章,可以发现,涉及的数据结构有链表(List)、(Stack)、映射(Map)、(Tree)、(Graph)等,涉及的编程思想和算法有Hash游标倒排索引排序递归搜索(广度优先、深度优先、二分搜索)、最短路径算法并查集等。当时学DS和ADS的时候上课尽顾着睡觉了,所以现在不得不重新拿起尘封已久的《数据结构与算法分析(C语言版)》(Mark Allen Weiss著 陈越姥姥改编),复习一下基本的东西,就把复习笔记发在这里好了,以便学完以后什么都不记得了。给出的示例代码有的是书上的代码,大部分是自己编写的测试代码,以便更深入理解。

    第一章为“简介”,介绍了递归的基本概念。此处省略。

    第二章“算法分析”,介绍算法的时间复杂度和空间复杂度的计算方法。作为例子书中介绍了四种常见的问题,分别是二分搜索、求最大公约数的欧几里得算法、最大子序列和问题、求幂问题。分别记录如下:

1. 二分搜索

二分搜索充分利用数组已经排过序的特性,将搜索的时间复杂度降为O(log2(n))

【示例代码】

#include 
using namespace std;

int BinarySearch(const int A[], int x, int n)
{
    int left = 0;
    int right = n - 1;

    while (left <= right){
        int middle = (left + right) / 2;
        if (x < A[middle]){
            right = middle -1;
        }
        else if (x > A[middle]){
            left = middle + 1;
        }
        else{
            return middle;
        }
    }
    return -1;
}

int main()
{
    int n = 8;
    int A[] = {1, 5, 8, 9, 11, 13, 14, 18};
    cout << BinarySearch(A, 11, n) << endl;
    cout << BinarySearch(A, 10, n) << endl;

    system("pause");
    return 0;
}

2. 求最大公约数的欧几里得算法

    即辗转相除法。下面给出的示例是Gcd的一个应用,即求任意两数互质的概率。

【示例代码】

#include 
using namespace std;

unsigned int Gcd(unsigned int M, unsigned int N)
{
    unsigned int Rem;
    while (N > 0){
        Rem = M % N;
        M = N;
        N = Rem;
    }

    return M;
}

void PrimePair(unsigned int N)
{
    int Rel = 0;
    int Tot = 0;
    for (int i = 1; i <= N; ++i){
        for (int j = i + 1; j <= N; ++j){
            ++Tot;
            if (Gcd(i, j) == 1){
                ++Rel;
            }
        }
    }
    cout << "The probability that two random numbers are relatively prime is about:"
    cout << (double)Rel / Tot << endl;

}
int main()
{
    cout << Gcd(1989, 1590) << endl;
    unsigned int N = 10000;
    PrimePair(N);
    system("pause");
    return 0;
}
3. 最大子序列和问题
下面的代码给出了两种方法,一种时间复杂度为O(n),一种用了分治思想,时间复杂度为O(nlog2(n))

【示例代码】

#include 

/* method 1*/
int MaxSubSum1(const int A[], int n)
{
    int thissum = 0;
    int maxsum = 0;

    for (int i = 0; i < n; ++i){
        thissum += A[i];
        if (thissum > maxsum){
            maxsum = thissum;
        }
        else if(thissum < 0){
            thissum = 0;
        }
    }

    return maxsum;
}

/*method 2*/
int MaxSubSum2entry(const int[], int, int);
int MaxSubSum2(const int A[], int n)
{
    return MaxSubSum2entry(A, 0, n - 1);
}

int max3(int, int, int);
int MaxSubSum2entry(const int A[], int left, int right)
{
    /*base case*/
    if (left == right){
        if (A[left] > 0){
            return A[left];
        }
        else{
            return 0;
        }
    }

    int middle = (left + right) / 2;
    int maxleft = MaxSubSum2entry(A, left, middle);
    int maxright = MaxSubSum2entry(A, middle + 1, right);
    int maxboardsumL = 0;
    int thisboardsumL = 0;
    for (int i = middle; i >= left; --i){
        thisboardsumL += A[i];
        if (thisboardsumL > maxboardsumL){
            maxboardsumL = thisboardsumL;
        }
    }
    int maxboardsumR = 0;
    int thisboardsumR = 0;
    for (int i = middle+1; i <= right; ++i){
        thisboardsumR += A[i];
        if (thisboardsumR > maxboardsumR){
            maxboardsumR = thisboardsumR;
        }
    }
    return max3(maxleft, maxright, maxboardsumL+maxboardsumR);
}
int max3(int a, int b, int c)
{
    int max = a > b ? a : b;
    int res = max > c ? max : c;
    return res;
}

int main()
{
    int n = 6;
    int A[] = {-2, 11, -4, 13, -5, -2};

    std::cout << MaxSubSum1(A, n) << std::endl;
    std::cout << MaxSubSum2(A, n) << std::endl;

    system("pause");
}
4. 求幂问题

如果直接用循环求,时间复杂度为O(n),改用递归实现,复杂度降O(nlog2(n))

【示例代码】

#include 
using namespace std;

long int pow(long int x, unsigned int n)
{
    if (n == 0){
        return 1;
    }
    if (n == 1){
        return x;
    }
    if (n % 2 == 0){
        return pow(x*x, n / 2);
    }
    else{
        return pow(x*x, n - 1)*x;
    }

}

int main()
{
    cout << pow(2, 10) << endl;
    system("pause");
    return 0;

}


To be continued...



你可能感兴趣的:(数据结构)