1.1什么是数据结构?
本文参考《数据结构(中国大学MOOC)》 from 浙江大学
一、数据结构的定义
对于“数据结构”,官方并没有一个统一的定义,本文选取了中文维基百科对数据结构的定义(自认为,这条看上去更易懂)
数据结构(Data Structure)是计算机存储、组织数据的方式。通常情况下,精心选择的数据结构可以带来最优效率的算法。不论是哪种定义,“数据结构”总是与“算法”一起讨论。(下一节就介绍,什么是算法)
二、解决问题的效率,与数据的组织方式有关
对存储在计算机中的数据,最基本的操作有:插入、删除、查找。
这就好比图书馆对书的管理,我们会面临的问题有:
- 新书怎么插入?
- 怎样找到某本指定的书?
- 如何对图书进行分类?如何分配各个不同类别的图书的存放空间?类别应该分多细?
由此类比计算机对数据进行处理,不难理解计算机解决问题的效率,与数据的组织方式密切相关。
三、解决问题的效率,与空间的利用率有关
????实现一个函数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处的值,。
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.利用乘法结合律和分配律重写多项式
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;
}
????计算给定多项式在给定点
处的值
.
完整程序如下:
#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;
}
运行结果:
可以看到,第二种方法运行的时间比第一种方法少了一个数量级,运行时间更短