听课笔记---数据结构(浙江大学)MOOC---第一周

第一周:预备知识—算法与数据结构

解决问题的策略效率与什么有关?

  1. 数据组织方式

    图书馆插入新书和查找书籍,用不同的数据组织方式,对应的操作就会有不同的时间复杂度。

    数据组织方式好坏的分析,与它所相关的操作有直接联系。

  2. 空间利用效率

    观察两段用于输出1到N的数字的代码

    其一循环算法:

    void PrintN(int N)
    {
    int i;
    for (i = 1; i <= N; i++) {
        printf("%d\n", i);
       }
    return;
    }

    其二递归算法:

    void PrintN(int N)
    {
    if (N) {
        PrintN(N - 1);
        printf("%d\n", N);
       }
    return;
    }

    第二段代码在数据过大时由于不断堆栈,空间爆炸,异常终止。

  3. 算法巧妙程度

    计算多项式在给定点x处的值,两段代码

    其一: f(x)=a0+a1x++an1xn1+anxn

    double f(int n, double a[], double x)
    {
    int i;
    double p = a[0];
    for (i = 1; i <= n; i++) {
        p += (a[i] * pow(x,i));
       }
    return p;
    }

    其二; f(x)=a0+x(a1+x((an1+x(an))))

    double f(int n, double a[], double x)
    {
    int i;
    double p = a[n];
    for (i = n; i > 0; i--) {
        p = a[i - 1] + x * p;
       }
    return p;
    }

    两段代码在运行时间上有很大区别,究其原因,将乘法视为关键操作,幂次视作多次乘法,则第一段代码算法 O(n2) , 第二段代码 O(n) .

测试(比较)算法运行效率小方法
#include<stdio.h>
#include<time.h>
#include<math.h>

#define MAX 100
double poly1(int n, double a[], double x)   // 坊间算法
{
    double p = 0;
    for (int i = 0; i <= n; i++) {
        p += a[i] * pow(x, i);
    }
    return p;
}

double poly2(int n, double a[], double x)   // 专业算法
{
    double p = a[0];
    for (int i = n; i > 0; i--) {
        p += a[i - 1] + p * x;
    }

    return p;
}

int main()
{
    double coef[MAX], x = 1.1;
    clock_t start, stop;

    for (int i = 0; i < MAX; i++) {
        coef[i] = i / 3.0;
    }

    start = clock();
    for (int i = 0; i < MAX; i++)
        poly1(MAX - 1, coef, x);
    stop = clock();

    printf("Polynomial Algorithm 1---plain Algorithm\n"
           "used ticks: %f\n\n", (double)(stop - start));

    start = clock();
    for (int i = 0; i < MAX; i++)
        poly2(MAX - 1, coef, x);
    stop = clock();

    printf("Polynomial Algorithm 2---professional Algorithm\n"
           "used ticks: %f\n\n", (double)(stop - start));
    return 0;
}

数据结构与抽象数据结构

数据结构
  • 数据对象在计算机中的组织方式
    • 逻辑结构
    • 物理存储结构
  • 数据对象与施加于其上的操作相关联
  • 实现操作的就是算法
抽象数据结构
  • 数据结构
    • 数据对象集
    • 与数据对象集相关的操作集
  • 抽象
    • 与物理存储方式无关
    • 与实现的算法和编程语言无关

只定义了对象集和操作集,不涉及如何实现。如下例:1

算法与最大子列和问题

熟悉问题,只敲了代码,在QuizCode里有

初识PTA

PTA是数据结构这门课采用的OJ系统。

  • 会将各个样例的特征标在Wrong Answer的标签旁边,便于Debug。
  • 函数填空题会将一些部分隐藏起来,因此看上去没有不代表没有,需仔细读题。
最大子列和(课堂算法)代码

课上讲的算法 O(nlogn) 实现

#include<stdio.h>
#include<stdlib.h>      // for malloc

int MaximumSubSum(int Data[], int s, int e);    // 寻找最大和
int max(int a, int b, int c);
int MaxCrossing(int Data[], int s, int e);      // Conquer 寻找跨越中间元素的最大和

int main()
{
    int * Data = NULL, Size = 0;

    scanf("%d", &Size);
    Data = malloc(sizeof(int) * Size);          // 动态分配内存

    for (int i = 0; i < Size; i++) {
        scanf("%d", &Data[i]);
    }
    int Max = MaximumSubSum(Data, 0, Size - 1); // 寻找
    printf("%d\n", Max);

    return 0;
}

int MaximumSubSum(int Data[], int s, int e)
{
    if (s == e) {                               // Base Case 只有一个元素
        if (Data[s] <= 0) {
            return 0;
        }
        else {
            return Data[s];
        }
    }

    int mid = (s + e) / 2;
    int Max1 = MaximumSubSum(Data, s, mid);
    int Max2 = MaximumSubSum(Data, mid + 1, e); // Divide, 递归求解
    int Max3 = MaxCrossing(Data, s, e);         // Conquer

    return max(Max1, Max2, Max3);
}

int max(int a, int b, int c)
{
    int result = a;
    if (result < b) {
        result = b;
    }
    if (result < c) {
        result = c;
    }

    return result;
}

int MaxCrossing(int Data[], int s, int e)
{
    int mid = (s + e) / 2, maxl = 0, maxr = 0, curr = 0;

    for (int i = mid; i >= s; i--) {    // 左侧最大
        curr += Data[i];
        if (curr > maxl) {
            maxl = curr;
        }
    }

    curr = 0;       // initialize
    for (int i = mid + 1; i <= e; i++) {// 右侧最大
        curr += Data[i];
        if (curr > maxr) {
            maxr = curr;
        }
    }

    return maxl + maxr;                 // 和为最大
}

算法 O(n) 实现

#include<stdio.h>

int main()
{
    int Size = 0, max = 0, curr = 0, Data = 0; // O(1) extra space

    scanf("%d", &Size);
    for (int i = 0; i < Size; i++) {
        scanf("%d", &Data);
        curr += Data;
        if (curr > max) {                       // refresh max
            max = curr;
        }
        if (curr < 0) {                         // discard curr
            curr = 0;
        }
    }

    printf("%d\n", max);

    return 0;
}
最大子列和(课后习题)代码

O(n) 实现

#include<stdio.h>
#include<stdlib.h>  // for malloc

int main()
{
    int Bool = 0, Size = 0, max = 0, curr = 0, curr_s = 0, curr_e = 0, s = 0, e = 0;
    int * Data; // O(n) extra space

    scanf("%d", &Size);
    Data = malloc(sizeof(int) * (Size + 1));
    for (int i = 0; i < Size; i++) {
        scanf("%d", &Data[i]);
    }
    curr_s = curr_e = s = e = Data[0];
    for (int i = 0; i < Size; i++) {
        curr += Data[i];
        curr_e = Data[i];
        if (curr < 0) {
            curr = 0;
            curr_s = Data[i + 1];
        }
        if (curr > max) {
            max = curr;
            s = curr_s;
            e = curr_e;
        }
    }
    if (max == 0) {         // 为0特判
        s = Data[0];
        e = Data[Size - 1];
        for (int i = 0; i < Size; i++) {
            if (Data[i] == 0) {
                s = e = 0;
                break;
            }
        }
    }
    printf("%d %d %d\n", max, s, e);

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值