什么是数据结构?
数据结构的定义:计算机中存储和组织数据的方式,通常选择好的数据结构可以带来最优效率的算法。
下面以三个例子来看
例1:如何在书架上摆放图书?
类比到计算机世界就是数据在存储空间中如何存放数据
图书的摆放要解决两个问题:、
- 新书如何插入
- 如何找到指定的书
实现的方法很多:
- 随便放--好放但是难找
- 按书名的拼音排序放--好找但是难放--每次都得把好多书都移动
- 先分类,在按书名的排序放--如何划分空间,如何分类
解决问题的效率,和数据的组织方式有关
例2:输入N,输出1-N的数字序列
这里使用了两种方法,循环和递归
#include<stdio.h>
//循环
void printN1(int N) {
for (int i = 0; i <= N; i++)
printf("%d ", i);
}
//递归
void printN2(int N) {
if (N) {
printN2(N - 1);
printf("%d ", N);
}
}
int main() {
int a = 0;
scanf_s("%d", &a);
printN1(a);
//printN2(a);
return 0;
}
其中递归的方法可能便于理解,但是其占用的内存空间可能很恐怖,进而导致程序异常终止
解决问题的效率,和空间的利用效率有关
例3:计算给定多项式在x点的值
//直接计算
double f(int n, double a[], double x) {
int i;
double p = a[0];
for ( i = 0; i <= n ; i++)
{
p += (a[i] * pow(x,i))
}
return p;
}
//秦九邵算法
double f1(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>
clock_t start,stop;
double duration;
int main(){
//准备工作写在开始之前
start = clock(); //开始计时
f();//测试函数,需要计时的一系列操作
stop = clock();//结束计时
//clock():捕捉程序运行到该行的时间
//CLK_TCK:机器时钟每秒走的时钟打点数
duration = (double)(stop - start)/CLK_TCK; //计算时间
//不在测试范围的处理写在其中
return 0;
}
//注释:这里的计时程序可能输出的结果是0,因为运行太快,无法捕捉
//多次运行程序,让其累计一个时间段,就可以比较出来
解决问题的效率,和算法的巧妙程度有关
所以什么是数据结构?
-
数据对象在计算机中的组织方式
-
逻辑结构
- 线性结构 一对一
- 树形结构 一对多
- 图形结构 多对多
-
物理存储结构:在机器的存放方式
- 数组
- 链表
-
抽象数据类型:通常用于描述数据结构
-
抽象:
- 与存放数据的机器无关
- 与数据存储的物理结构无关
- 与实现操作的算法和编程语言无关
- 只描述是什么,不关心如何做到
-
数据类型:在比较高级的程序语言中,这就是一个类
- 对象
- 操作:完成操作的方法就是算法
-
-
举例来理解抽象:
对于矩阵,不在乎其如何实现,其具体的数据类型是什么,不在乎用什么语言实现
思考:为什么要抽象?抽象有什么好处?
我的理解:抽象可以方便的解决某一类共性问题
什么是算法?
-
一个有限的指令集
- 每一条指令有明确的目标,不能有歧义
- 计算机能处理的范围之内
- 描述的手段应该抽象
-
接受输入
-
至少产生一个输出
-
有限步骤
什么是好的算法?
时间复杂度和空间复杂度都要低
空间复杂度S(n):算法写成的程序在执行时占用的存储单元的长度。
- 往往与输入的规模有关
- 复杂度过高算法可能会内存超限,导致程序异常中断
空间复杂度T(n):算法写成的程序在执行时所耗费时间的长度。
- 常常与输入的规模有关
- 复杂度过高可能永远等不到结果
在分析一般算法的效率时,常常关注最坏情况复杂度
我们关心随着数据规模逐渐增大(当n充分大的时候),算法的复杂度如何增长
复杂度的渐进表示法:取最大下界和最小上界
可以看到2的n次方以上,一个很小的输入最后的输出规模就很大
复杂度分析:多写算法多练吧