《数据结构》第一讲基本概念
1.1什么是数据结构
1.1.1关于数据组织-例:图书摆放
”数据结构是数据对象,以及存在于该对象的实例和组成实例的数据元素之间的各种联系。这些联系可以通过定义相应的函数来给出。“ Sartaj Sahni《数据结构、算法与应用》
”数据结构是ADT(抽象数据类型Abstract Data Type)的物理实现“ Clifford A.Shaffer 《数据结构与算法分析》
”数据结构(data structure)是计算机中存储、组织数据的方式。通常情况下,精心选择的数据结构可以带来最优效率的算法。“ 中文维基百科
例1:如何在书架上摆放图书?
数据如何组织和规模有关系。
图书的摆放要使得两个操作方便实现,操作1:新书怎么插入。操作2:怎么找到某本指定的书。
方法1:随便放。操作1:哪里有空放哪,一步到位。操作2:难以实现。
方法2:按照书名的拼音字母顺序排放。操作1:难以实现,比如新进一本《阿Q正传》,则要将之后的书一本一本往后错位,直到前面留出空当为止。操作2:二分查找。
方法3:把书架划分成几块区域,每块区域指定摆放某种类别的书,每种类别内,按照书名的字母拼音顺序排放。操作1:先定类别,二分查找确定位置,移出空位。操作2:先定类别,再二分查找。
基于方法3,问题:空间如何分配?类别应该分多细?
上述例子说明,解决问题方法的效率,跟数据的组织方式有关。
讨论1.1 对中等规模、大规模的图书摆放,你有什么更好的建议?
答:先分大类,大类可以再细分小类,基于合适的数量时,再利用拼音字母顺序摆放。也可以利用计算机建立索引目录,对所有书按类别,按出版时间,按作者等以不同方式进行编号,可以通过不同的检索条件,快速查找到图书。
1.1.2关于空间使用-例:PrintN函数实现
例2:写程序实现一个函数PrintN,使得传入一个正整数为N的参数后,能顺序打印从1到N的全部正整数
循环实现:
- void PrintN(int N)
- {
- for(int i = 1;i < N;i++)
- printf("%d\n",i);
- return;
- }
- void PrintN(int N)
- {
- if(N)
- {
- PrintN(N - 1);
- printf("%d\n",N);
- }
- return;
- }
因为递归程序对空间占用很大,上述程序就是因为递归程序用完了能用的空间,非正常终止了。
上述例子说明,解决问题方法的效率,跟空间的利用效率有关。
1.1.3关于算法效率-例:计算多项式值
例3:写程序计算给定多项式在给定点x处的值多项式:f(x) = a0 + a1*x + a2*x^2 + ……+ an-1*x^(n-1) + an*x^n
最直接的算法:
- double f1(int n,double a[],double x) //n为阶数,系数放在数组a中,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) //n为阶数,系数放在数组a中,x为要计算的点
- {
- int i;
- double p = a[n];
- for(int i = n;i > 0;i--)
- p = a[i-1] + x * p;
- return p;
- }
我们开始比较两种函数的运行时间:
C语言提供了clock():捕捉从程序开始运行到clock()被调用时所耗费的时间。这个时间单位是clock tick,即”时钟打点“。常数CLK_TCK:机器时钟每秒所走的时钟打点数。
常用的计算函数运行时间的模板:
- #include <stdio.h>
- #include <time.h>
- clock_t start,stop; //clock_t 是clock函数返回的变量类型
- double duration; //记录被测函数运行时间,以秒为单位
- int main(void)
- {
- //不在测试范围内的准备工作写在clock()调用之前
- start = clock(); //开始计时
- MyFunction();//把被测函数加在这里
- stop = clock();//停止计时
- duration = ((double) (stop - start)) / CLK_TCK; //计算运行时间
- //其他不在测试范围的处理写在后面,例如输出duration的值
- return 0;
- }
-