1.1什么是数据结构

什么是数据结构

官方定义没有,相关的三个定义如下:

  • 数据结构是数据对象,以及存在于该对象的实例和组成实例的数据元素之间的各种联系,这些联系可以通过定义相关的函数给出。——《数据结构、算法与应用》

  • 数据结构是ADT(抽象数据类型)的物理实现——《数据结构与算法分析》

  • 数据结构是计算机中存储、组织数据的方式。通常情况下,精心选择的数据结构可以带来最优效率的算法——《中文维基百科》

听起来有一点复杂,我们通过三个例子来了解:

1.关于数据组织——例:图书摆放

例1:如何在书架上摆放图书:

这个问题很不科学,因为这是跟数据规模相关的问题,这个问题难度不在怎么放书,而是难在于放书是为了做什么事情用的

如果只有几本书放在一个小书架,随便放就很轻松;如果是自家书房几百本书,随便放就很麻烦;而如果要是大图书馆那种成千上万本书,那你如果随便放,你要查找一本书有没有的时候,你不知道有没有就必须从头查找一遍,浪费很多很多时间。

图书的摆放需要2个相关的操作方便实现:

  • 新书怎么插入?

  • 怎么找到某本指定的书?

①方法1:随便放

  • 新书怎么插入?

哪儿有空就放哪儿,一步到位很简单。

  • 怎么找到某本指定的书?

如果规模较小还不是很麻烦,如果规模很大,就像图书馆那种,你找一本书得累死,犹如大海捞针一样。

②方法2:按照书名的拼音字母顺序排放

  • 新书怎么插入

所有书都得一本一本往后挪,很麻烦!

  • 怎么找到某本指定的书

可以用二分查找法,很快就能查到要找的书。

③把书架划分成几块区域,每块区域指定摆放某种类别的书;在每种类别内,按照书名的拼音字母顺序排放

  • 新书怎么插入

先定类别,二分查找确定位置,移除空位再插入,虽然还是要移位再插入,但是要移动的书的数量会少很多很多。

  • 怎么找到某本指定的书

先定类别,再二分查找法。如在大图书馆里找一本数据结构的书,先在计算机类的书里查,然后再用二分查找法查找,数据规模相比于整个图书馆里书的规模会小很多,速度快很多。

这个例子说明:解决问题方法的效率,跟数据的组织方式有关。

2.关于空间使用——例:printN函数的实现

例2:写程序实现一个函数printN,使得传入一个正整数为N的参数后,能顺序打印从1到N的全部正整数

①方法1:直接for循环打印

void printN(int n) {
	for (int i = 0; i < n; ++i) {
		cout << i << endl;
	}
}

②方法2:递归打印

void printND(int n) {
	if (n) {
		printND(n - 1);
		cout << n << endl;
	}
}
int main() {
	printN(10000);  
	printND(10000); //出现中断
}

虽然这个例子所花费的时间差不多,但是递归法十分占用空间,当输入规模十分大时,递归所需要的空间太大,内存不够用出现断点。

这个例子说明:解决问题方法的效率,跟空间的利用率有关

3.关于算法效率——例:对1到n求和

求程序耗费时间的函数:clock():

  • clock():捕捉从程序开始运行到clock()被调用时所耗费的时间。这个时间的单位是clock tick,即”时钟打点“。
  • 常数CLK_TCK:机器时钟每秒所走的时钟打点数。

通过这两个可以算出一个函数调用所花费的时间:

#include<time.h>
#include<iostream>

int main() {
    clock_t start, end;
    start = clock();
    //所要测试花费时间的代码
    end = clock();
    cout << "耗费时间为:" << ((double)(end - start)) / CLK_TCK
         << " s" << endl;
}

例如:对1到n求和

①方法1:暴力求解for循环

int sum1(int n) {
    int sum = 0;
    for (int i = 1; i <= n; ++i) {
        sum += i;
    }
    return sum;
}

②方法2:利用公式sum = (1 + n) / 2

int sum2(int n) {
    int sum = 0;
    sum = (1 + n) / 2;
    return sum;
}

利用上述测算方法对这两个函数调用进行测试:

int main() {
	clock_t start, end;
	start = clock();
	int s1 = sum1(100000000);
	//int s2 = sum2(100000000);
	end = clock();
	cout << "耗费时间为:" << ((long double)(end - start)) / CLK_TCK << " s" << endl;
}
//运行结果为
0.165 s
int main() {
	clock_t start, end;
	start = clock();
	//int s1 = sum1(100000000);
	int s2 = sum2(100000000);
	end = clock();
	cout << "耗费时间为:" << ((long double)(end - start)) / CLK_TCK << " s" << endl;
}
//运行结果为:
0 s

如果一个函数运行速度太快,导致看不出时间,则可以重复调用一个函数,然后除以被调用的次数即可算出一次的时间:

如上述第二次调用速度看不出花费时间,我们对其调用多次

int main() {
	clock_t start, end;
	start = clock();
	//int s1 = sum1(100000000);
	int cnt = 100000000;
	while (cnt--) {
		int s2 = sum2(100000000);
	}
	end = clock();
	cout << "耗费时间为:" << ((float)(end - start)) / CLK_TCK  << " s" << endl;
}
//运行结果为:
1.039 s
//实际运行一次的时间为:
1.039 × 10e-8 s

这个例子告诉我们:解决方法的效率跟算法的巧妙程度有关

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值