数据结构看公开课后理解加深,根据课上讲解,自己又回忆了一 遍!!!

什么是数据结构

通过听浙大公开课和《数据结构与算法分析》这本书,我将从以下四点来展开,我对数据结构的认识。1.关于数据组织;2.关于空间使用;3.关于算法效率;4抽象数据类型(ADT)

1.关于数据组织

你有大量图书需要摆放,将有以下三种方法摆放:
1.随便放,放的时候一步到位,哪里有空哪里放,但查找的时候需要遍历每一本藏书;
2.按照书名的拼音字母顺序摆放,插入时候需要把每本书一个一个后移,让我插进来,但查找时候则二分查找,每次缩小一半范围;
3.先划分区域,分类(工科,理科,文科。农科等等),再按拼音字母顺序摆放,插入先确定类别,再在确定类别中移动每一本书,挪出空间,查找时候可以先确定类别,再在确定的类别中二分查找;

上面三种方法对比,无疑第三种方法要好很多,也是图书馆现在所使用的方法,但第三种方法任存在以下两种问题,空间该如何分配和类型该分多细,如空间分配过多,那么有大量的空间闲置浪费,空间分配过少,每次插入新书空间不够,就要增加书架,就很麻烦;同样地,类别应分多细,如类别分过粗,30万本书,分为理科,文科(理科里有化学,物理等等),这内部数据过多15万,任然难以处理;类别分过细,光类别分3万种,每种含10本书,内部数据很好处理,但3万的类别又处理不了。所以我们要找到合适的类别分类和空间分配。
解决问题方法的效率跟数据的组织方式相关

2.关于空间使用

对于任何一个简单的问题都至少有两种不一样的实现方法,下面例子将通过循环实现和递归实现
在这里插入图片描述
在这里插入图片描述

上述分别为循环实现和递归实现,令N=10,100,1000,10000,100000等,当N值较小时我们会得到相同的结果,但当N变大时,如N为100000时,会发生一下结果
在这里插入图片描述
在这里插入图片描述

我们会发现循环实现需要一段时间,但仍可得到我们想要的结果,而递归实现则直接出错,没有结果显示,因为递归对空间的利用很恐怖,堆积在栈中,数据过多,导致栈爆掉;
解决问题方法的效率跟空间利用率相关

关于算法效率

写程序计算给定多项式在给定点x处的值
C语言提供函数clock()和pow()

其中clock()在头文件<time.h>中,捕捉程序开始运行到clock()的调用之间所耗费的时间,时间单位为clock tick,即叫做时钟打点;(常定义clock_t start, stop 其中clock_t是clock ()函数的返回类型)
常数CLK_TCK:机器每秒钟所走的时钟打点数

pow()在头文件<math,h>中,用来求x的y次幂;

对于多项式一般而言有以下两种表达方式,如
F ( x ) = ∑ 0 9 i x i F(x) = ∑_0^9 ix^{i} F(x)=09ixi
多项式声明double f(int n, double a[], double x)
n指最高次数, a[ ]指由每一项前的系数组成的数组,x指未知数

通常采用下列方法2,原因后续解释
第一种方法一般方法,利用pow()函数,从次数从小到大递增

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

第二种方法,每次向外提出一个x,即从内向外(次数由大到小递减)

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

源代码如下:

#include <stdio.h>
#include <time.h>
#include <math.h>
#define MAXN 10
clock_t start, stop;
double duration;
double f1(int n, double a[], double x);
double f2(int n, double a[], double x);

int main() {
	double a[MAXN];
	for (int i = 0; i < MAXN; i++)
		a[i] = i;
	start = clock();
	f1(MAXN - 1, a, 1.1);
	stop = clock();
	duration = ((double)(stop - start)) / CLK_TCK;
	printf("ticks1 = %lf\n", (double)(stop - start));
	printf("duration1 = %6.2e\n", duration);

	start = clock();
	f2(MAXN - 1, a, 1.1);
	stop = clock();
	duration = ((double)(stop - start)) / CLK_TCK;
	printf("ticks2 = %lf\n", (double)(stop - start));
	printf("duration2 = %6.2e\n", duration);

	return 0;
}

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

运行该程序,得到结果如下:
在这里插入图片描述
得到的结果没有差别,是因为两个函数跑太快,为了计算这两个函数跑一次所需要的时间,我们可以加入一个for循环,让它跑 1 0 7 10^7 107次,然后求平均值,便可求得一次所需时间

#include <stdio.h>
#include <time.h>
#include <math.h>
#define MAXN 10
#define MAXK 1e7  //被测函数重复调用次数
clock_t start, stop;
double duration;
double f1(int n, double a[], double x);
double f2(int n, double a[], double x);

int main() {
	double a[MAXN];
	for (int i = 0; i < MAXN; i++)
		a[i] = i;
	start = clock();
	for (int i = 0; i < MAXK; i++)   //for循环,重复调用10的7次方次
		f1(MAXN - 1, a, 1.1);
	stop = clock();
	duration = ((double)(stop - start)) / CLK_TCK/MAXK;
	printf("ticks1 = %lf\n", (double)(stop - start));
	printf("duration1 = %6.2e\n", duration);

	start = clock();
	for (int i = 0; i < MAXK; i++)
		f2(MAXN - 1, a, 1.1);
	stop = clock();
	duration = ((double)(stop - start)) / CLK_TCK/MAXK;
	printf("ticks2 = %lf\n", (double)(stop - start));
	printf("duration2 = %6.2e\n", duration);

	return 0;
}

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

得到的结果出现一个数量级的差异
在这里插入图片描述
利用函数指针简化代码,源代码如下:

#include <stdio.h>
#include <time.h>
#include <math.h>
#define MAXN 10
clock_t start, stop;
double duration;
double f1(int n, double a[], double x);
double f2(int n, double a[], double x);
void f_get(double(* f)(int n, double a[], double x), double a[]);

int main() {
	double a[MAXN];
	for (int i = 0; i < MAXN; i++)
		a[i] = i;
	f_get(f1, a);
	f_get(f2, a);

	return 0;
}
void f_get(double(* f)(int n, double a[], double x), double a[]) {
	start = clock();
	(*f)(MAXN - 1, a, 1.1);
	stop = clock();
	duration = ((double)(stop - start)) / CLK_TCK;
	printf("ticks = %lf\n", (double)(stop - start));
	printf("duration = %6.2e\n", duration);

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

第一个算法比第二个算法慢了差不多一个数量级,这也就是我们选择方法2的原因。
解决问题的方法的效率跟算法的巧妙程度相关

4.抽象数据类型

什么是数据结构
数据对象在计算机中的组织方式;
1.逻辑结构:a.一对一:线性结构; b.一对多,树形结构; c.多对多,图型结构
2.物理存储结构:数组存储(连续存储),链表存储(任意存储)
数据对象必定与一系列加在其上的操作相关联;
完成这些操作所用的方法就叫算法;

抽象数据类型(ADT)

数据类型: a.数据对象集; b.数据集合相关联的操作集
数据类型在C语言里独立处理,在一些面向对象的语言,如C++,Java等,存在“类”, 把数据集和操作集封装在一个类里面

抽象:描述数据类型的方法不依赖于具体实现
1.与存放数据的机器无关
2.与数据存储的物理结构无关
3.与实现操作的算法和编程语言无关

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值