1.1什么是数据结构?

                                                            本文参考《数据结构(中国大学MOOC)》 from 浙江大学

一、数据结构的定义

        对于“数据结构”,官方并没有一个统一的定义,本文选取了中文维基百科对数据结构的定义(自认为,这条看上去更易懂)

数据结构(Data Structure)是计算机存储、组织数据的方式。通常情况下,精心选择的数据结构可以带来最优效率的算法。不论是哪种定义,“数据结构”总是与“算法”一起讨论。(下一节就介绍,什么是算法)

 

二、解决问题的效率,与数据的组织方式有关

对存储在计算机中的数据,最基本的操作有:插入删除查找

这就好比图书馆对书的管理,我们会面临的问题有:

  1. 新书怎么插入?
  2. 怎样找到某本指定的书?
  3. 如何对图书进行分类?如何分配各个不同类别的图书的存放空间?类别应该分多细?

由此类比计算机对数据进行处理,不难理解计算机解决问题的效率,与数据的组织方式密切相关。

 

三、解决问题的效率,与空间的利用率有关

?实现一个函数PrintN,使得传入一个正整数为N的参数后,能顺序打印从1到N的全部正整数。

1.for循环实现

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

2.递归实现

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

完整的测试程序:

#include <stdio.h>

void PrintN(int N);
int main()
{
    int N;
    scans("%d",&N);
    PrintN(N);
    return 0;
}

测试结果如下:

测试时,当输入N=100,0000时,for循环程序可正常执行,而递归程序报错。

                     

                  图1  for循环执行结果                                                   图2 递归程序执行结果

          解释一下原因:

四、解决问题的效率与算法的巧妙程度有关

?写程序计算给定多项式在给定点x处的值,f(x)=a_{0}+a_{1}x+...+a_{n-1}x^{n-1}+a_{n}x^{n}

1.直接根据多项式写

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;
}

2.利用乘法结合律和分配律重写多项式f=a_{0}+x(a_{1}+x(...(a_{n-1}+x(a_{n}))...))

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

3.比较两种不同的方式运行的时间⌚️

clock():捕捉从程序开始运行到clock()被调用时所耗费的时间,其单位为clock tick,即“时钟打点”。

常数CLK_TCK(或CLOCKS_PER_SEC):机器时钟每秒(s)所走的时钟打点数。

打印了一下我的机器的CLOCKS_PER_SEC:

要测试一个函数的运行时间,示例程序如下:

#include <stdio.h>
#include <time.h>    //要使用clock()函数需要引用该头文件

clock_t start,stop;   //clock_t 是clock()函数返回的变量类型
double duration;      //记录被测函数运行的时间,以秒(s)为单位

int main()
{
  /*不在测试范围内的准备工作写在clock()调用之前*/
    start=clock();     //start得到的是从main()函数开始运行,到这一句程序所走的时钟打点数
    Myfunction();
    stop=clock();
    duration=((double)(stop-start))/CLOCKS_PER_SEC;   //计算运行时间,单位为s

    return 0;
}   

如果得到的结果为0,说明函数运行的时间很短,其运行所需的时钟打点数<CLOCKS_PER_SEC,解决这一问题的方法就是:重复,即让被测函数重复运行多次,使得测出的总的时钟打点数充分长,最后计算被测函数平均每次运行所需时间即可。

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

#define MAXK 1e7
……

clock_t start,stop;   //clock_t 是clock()函数返回的变量类型
double duration;      //记录被测函数运行的时间,以秒(s)为单位
int main()
{
  /*不在测试范围内的准备工作写在clock()调用之前*/
    start=clock();     //start得到的是从main()函数开始运行,到这一句程序所走的时钟打点数
    for(I=0;i<MAXK;i++)    
        Myfunction();
    stop=clock();
    duration=((double)(stop-start))/CLOCKS_PER_SEC/MAXK;   //计算运行时间,单位为s
    printf("ticks=%f\n",duration);
    printf("duration=%6.2e\n",duration);
    return 0;
}   

?计算给定多项式f(x)=\sum_{i=0}^{9}i\cdot x^{i}在给定点x=1.1处的值f(1.1).

完整程序如下:

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

clock_t start,stop;
double duration;
#define MAXN 10       /*多项式最大项数,即多项式阶数+1*/
#define MAXK 1e7      /*函数重复执行次数*/
double f1(int n,double a[],double x);
double f2(int n,double a[],double x);
int main()
{
    int i;
    double a[MAXN];   //存储多项式系数
    for(i=0;i<MAXN;i++) a[i]=(double)i;
    
    start=clock();
    for(i=0;i<MAXK;i++)
        f1(MAXN-1,a,1.1);
    stop=clock();
    duration=((double)(stop-start))/CLOCKS_PER_SEC/MAXK;
    printf("ticks1=%f\n",(double)(stop-start));
    printf("duration1=%6.2e\n",duration);
    
    start=clock();
    for(i=0;i<MAXK;i++)
        f2(MAXN-1,a,1.1);
    stop=clock();
    duration=((double)(stop-start))/CLOCKS_PER_SEC/MAXK;
    printf("ticks2=%f\n",(double)(stop-start));
    printf("duration2=%6.2e\n",duration);
    return 0;
}

double f1(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;
}

double f2(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;
}

运行结果:

    可以看到,第二种方法运行的时间比第一种方法少了一个数量级,运行时间更短

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值