数据结构第一讲

第一个例子

老师以书架上存放书为例子来讨论。
在书架上如何防治书呢?要考虑书的规模。
第一种方案:
放书的方式,随便放
如何查找呢?所有的都要遍历。如果书的规模很大时,找一本书将会花很多时间。

第二种方案:
按照字母顺序存储书籍,我们找一本书时,可以按照字母顺序找书,但是放置书的时候,需要后移所有的书籍才能插入进去。也有缺点。

第三种方案:
结合实际。我们将书首先归类,将大规模的书籍划分到一个类中,然后再去按照二分查找方法找书。

如何进行分类呢?每类书籍要分配多大的空间呢?我们分类时,要分多细致呢?

启示

总结,解决问题的方法和数据的组织方式是相关的。

第二例子

写一个printN函数,该函数能够将N正整数以下的每个数据依次打印出来。有两种方案。
第一种方案:
main函数:

#include <stdlib.h>
#include <stdio.h>

#define LINE_MAX 16
static int printN1(int N);
static int printN2(int N);

int main(void)
{
  int ret = 0;
  int n = 100;
  printf("\n use printf 1 is :\n");
  printN1(n);
  printf("\n use printf 2 is :\n");
  printN2(n);
 printf("\n");
}

循环过程:


static int printN1(int n)
{
    int line = LINE_MAX;
    int i = 0;

    if(n <= 0)
    {
        return -1;
    }


    for(i = 0;i < n;i++)
    {
        if((n-i)%line == 0)
            printf("\n");
        printf("%d,",n-i);
    }
    return 0;
}

迭代过程:


static int printN1(int n)
{
    int line = LINE_MAX;
    int i = 0;

    if(n <= 0)
    {
        return -1;
    }


    for(i = 0;i < n;i++)
    {
        if((n-i)%line == 0)
            printf("\n");
        printf("%d,",n-i);
    }
    return 0;
}

10万次的程序执行结果为:
这里写图片描述
使用递归的算法的时候,当迭代次数为10万次的时候,仍然能够递归打印输出。改为100万次,只能输出825472次就结束了,出现segment段错误。表示进程的所有的空间已经被占据全部,仍然不够程序使用。

100万次后递归的执行结果
这里写图片描述

启示

这里,老师说程序的执行效率与程序占用的空间是有关系的。
但是这里程序已经无法执行了,何谈效率呢?当然递归也算是一种算法,是一种解决方式,影响了程序的执行结果。

第三个例子

多项式
F(x)=a0+a1 x1 +….+an * xn
main函数

int main(void)
{
    int ret = 0;
#if 0
    int n = 100;
    printf("\n use printf 1 is :\n");
    printN1(n);
    printf("\n use printf 2 is :\n");
    printN2(n);
    printf("\n");
#endif
    int n = 10;
    double a[11] = {12,14,33,33,42,43,89,33,67,56,45};
    int x = 4;
    int sum = 0;
    printf("\n use f1 is :\n");
    sum = f1(n,a,x);
    printf("sum is:%d;\n",sum);
    printf("\n use f2 is :\n");
    sum = f2(n,a,x);
    printf("sum is:%d;\n",sum);

}

直接转化:

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

    return p;
}

提取公因式

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

    return p;
}

运行结果是:

shiyanlou:Code/ $ gcc  -o test a.c -lm                               [23:23:25]
shiyanlou:Code/ $ ./test                                             [23:26:20]

 use f1 is :
sum is:67219604;

 use f2 is :
sum is:67219604;
shiyanlou:Code/ $  

启示

解决问题的效率和运用算法的巧妙程度有关系。

练习

求如下多项式的和
给定另一个100阶多项式 ,用不同方法计算并且比较一下运行时间?
F(x)=1+1 x1 +….+ 1n * xn
main函数中增加时间计算:

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <time.h>

static double f3(double x);
static double f4(double x);

int main(void)
{
    int ret = 0;
    int n = 100;
    double a[100] = {0};
    int x = 4;
    double sum = 0;
    int i = 0;
    time_t start,stop;
    double  duration;
    int time = 1000;

    x = 1.1;
    printf("\n use f3 is :\n");
    start = clock();
    for(i = 0;i < time;i++)
        sum = f3(x);
    stop = clock();
    printf("sum is:%f;\n",sum);
    duration =(double) (stop - start) / (CLOCKS_PER_SEC);
    printf("duration = %f\n",duration);

    x = 1.1;
    printf("\n use f3 is :\n");
    start = clock();
    for(i = 0;i < time;i++)
        sum = f4(x);
    stop = clock();
    printf("sum is:%f;\n",sum);
    duration =(double) (stop - start) / (CLOCKS_PER_SEC);
    printf("duration = %f\n",duration);

}

直接翻译的代码:

static double f3(double x)
{
    double  p = 0;
    int     i = 0;
    double  a[101];

    for(i = 1;i <= 100;i++)
        a[i] = (double)1/i;

    for(i = 1;i <= 100;i++)
        p += a[i]*pow(x,i);
    p++;

    return p;
}

经过提取公因子x后,函数实现为:


static double f4(double x)
{
    double  p = 0;
    int     i = 0;
    double  a[101];

    for(i = 1;i <= 100;i++)
        a[i] = (double)(1)/(double)(i);

    p = a[100]; 
    for(i = 99;i > 0 ;i--)
    {
        p = (a[i] + x*p);
    }

    p++;

    return p;
}

结果:

这里写图片描述

通过测试结果可以看到第一种方法的耗时是第二种方法耗时的5倍左右。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值