1.数据结构
是计算机组织数据和存储数据的方式;(它是指一组相互之间存在一种或多种关系的数据的组织方式和存储方式,以及在该数据上的一组操作)
数据结构=数据的逻辑结构+数据的储存结构+数据的基本运算
2.数据结构 算法和算法
算法+数据结构=程序
(1976年瑞士尼克劳斯.维尔特[Niklaus wirth提出]
数据结构=数据的逻辑结构+数据的储存结构+数据的基本运算
3.小知识
- 数据:所有能被计算机处理的符号的集合
- 数据元素:一个数据集合的个体即数据的基本单位
- 数据项:数据项是数据具有意义的最小单位(数据库中数据项又称为字段/域,数据数据不可分割IDE最小标识单位)
- 实际问题中的数据称为原始数据
4.数据的逻辑结构物理结构
逻辑结构:是指数据及数据的组织方式 是指数据之间的结构关系
物理结构:是指数据及存储方式 是数据结构在机内的表示,数据的逻辑结构在计算机中的实现
- 存储节点:每个存储节点存放一个数据元素数据元素之间关联方式的表示
- 数据元素结构的存储=数据元素的存储+元素逻辑关系的存储.
5.数据的逻辑结构
- 集合:任意两个节点之间都没有链接关系,组织形式松散.
- 线性结构:起始结构和终止节点外,每个节点有一个前驱和一个后继.(节点按逻辑关系依次排成一条链,节点之间一个一个依次相链接)
- 树形结构:构成树,即每个元素最多有一个前驱,可以有多个后继.(具有分支,层次特性,上层的节点可以和下层多个节点相邻接,但下层节点只能和上层的一个节点相邻接)
- 图结构:最复杂,任何两个节点都可以相邻接
数据的逻辑结构 不受数据元素的形式内容 数据元素的节点个数 数据元素的相对位置影响
6.数据的存储结构
- 顺序存储方式
- 链式存储方式
- 索引存储方式
- 散列存储方式
顺序结构
- 顺序存储方式:借助数据元素的相对位置来表示数据的逻辑结构;
- 线性表的顺序存储方法:将表的节点一次存放在计算机内存中一组连续的存储单元中.
- 顺序的方法:将元素存储到一片连续的存储区.
特点
- 预先分配好长度,需要预估存储数据需要的存储量;
- 插入和删除需要移动其他元素;
- 存储快捷,是随机存取结构
链式结构
链式存储方式:借助数据元素地址的指针表示数据的逻辑结构;
数据项 指针项
特点
- 动态分配,不需要预先确定内存分配;
- 插入和删除不需要移动其他元素;
- 非随机存取
索引存储方式:借助索引表中的索引指示各存储节点的存储位置.
散列存储方式:用散列函数指示各节点的存储位置
运算:
指在某种逻辑结构上施加的操作,即对逻辑结构的加工
加工型运算:其操作改变原逻辑结构的值:如:节点数,节点内容.
引用型运算:其操作不改变元逻辑结构的值.
基本运算
- 建立
- 查找
- 读取
- 插入
- 删除
算法
算法规定了求解给定问题所需的所有处理步骤,及执行顺序,使给定类型问题能在有限时间内被机械的求解.
算法必须使用某种语言描叙:
- 程序
- 介于自然语言和程序设计语言的伪代码
- 非形式算法(自然语言)
- 框图(N-S图)
一个算法是指对特定问题求解步骤的一种描叙,它是指令的有穷序列.
算法具有以下特性:
- 有穷性:一个算法总是在执行有穷步后结束.
- 确定性:算法的每一步都是必须是明确的定义的.
- 可行性:算法的每一步都是可以通过实际操作来完成的.
- 输入:一个算法有零个后者多个输入,这些输入取自特定的对象集合.
- 输出:一个算法有一个或者多个输出,它们是与输入有特定关系的量.
算法的设计满足:
- 准确性:对于合法的输入产生符合要求的输出
- 易读性:算法应该易读.便于交流.这也是保证算法准确性的前提;添加注释也是一种增加可读性的办法
- 健壮性:当输入非法数据时,算法还能正常做出适当的反应而不会崩溃,输出错误信息;算法中应该考虑适当的错误处理
- 时空性:指算法的时间复杂度和空间复杂度,算法分析主要分析算法的时间复杂度和空间复杂度,目的是提高算法的效率
选择最优算法的2个度量
- 时间复杂度:算法运行时的总步数,通常是问题规模的函数
- 空间复杂度:算法执行时所占用的存储空间,通常是问题规模的函数
算法的计算量
-
合理的选择一种或几种操作作为标准操作
无特殊说明,默认赋值语句作为标准操作 -
确定每个算法总执行多次标准操作,并将此次数规定该算法的计算量
-
算法的最坏情况时间复杂度:以算法在所有输入下的计算量的最大值作为最大值作为算法的计算量.
-
算法平均情况的时间复杂度:以算法在所有输入下的计算量的加权平均值作为算法的计算量.
-
最坏情况时间复杂度和平均情况时间复杂度统称为时间复杂度.
void max1(int a,b,c,d)
{
a*=d;b*=d:c*=d;
if(a>b)x=a;
else x=b;
if(c>x)x=c
printf("%d\n",x)
}
max1的最坏时间复杂度为:5(注意:if和else看做一个模块,最多5赋值语句)
void max2(int a,b,c,d)
{
if(a>b) x=a;
else x=b;
if(c>x) x=c;
x*=d;
printf("%d\n",x)
}
算法max2的最坏时间复杂度为3
int fact1(int n)
{
int i,j,temp,s;
s=0;
for(i=1;i<=n;i++){
temp=1;
for(j=1;j<=i;j++){
temp=temp*j;
s=s+temp;
}
}
return s;
}
时间复杂度 o(n^2)
int fact2(int n)
{
int i,j,temp,s;
s=0;temp=1;
for(i=1;i<n;i++)
{
temp=temp*i;
s=s+temp;
}
return s;
}
o(n)
常见的时间复杂度按数量级递增排列依次为:
常数O(1),对数阶O(log2^n),线性阶O(n),线性对数阶O(nlog2 ^n),平方阶O(n ^2),多项式阶O(n ^c),指数阶O(c ^n)
我们将时间复杂度记为输入数据规模n的函数,若解决问题需要执行n^2次操作,则记为O(n ^2).
空间复杂度
是对算法在执行过程中临时占有储存空间大小的度量.
一个算法在执行期间所需要的存储空间量包括以下部分:
- 程序代码所占用的空间;
- 输入数据所占用的空间
- 辅助变量所占用的空间值;
估算算法空间复杂度时,一般只分析变量辅助所占的空间
void f1(int a[],int n)
{
int i,temp;
for(i=0;i<n/2-1;i++){
temp=a[i];
a[i]=a[n-1-i];
a[n-1-i]=temp
}
}
O(1)
void f2(int a[],int n)
{
int i,b[100];
for(i=0;i<=n-1;i++)
b[i]=a[n-1-i];
for(i=0;i<n-1;i++)
a[i]=b[i];
}
O(n)注意 一个for循环为n 嵌套for循环 n ^2
int product =1;
for(i=n;i>0;i--)
for(j=1;j<=n;j++)
product*=j;
基本操作次数
T(n)=1+2+…(n+1)n/2
时间复杂度
t(n)=O(n ^2)