随着计算机应用领域的扩展,计算机越来越多地用于非数值的计算。
操作对象
:每位学生的信息(学号、姓名、性别、籍贯、专业等)。
操作算法
:查询、插入、修改、删除等。
操作对象之间的关系
:除了开头行和结尾行的操作对象,其余操作对象的行前后都有其他操作对象,操作对象就像被一根绳子串起来的关系称为 线性关系。
数据结构:线性数据结构、这样一个表格就称为(线性表)。
操作对象之间并不是一个串着一个,操作对象后面不再是一个跟着一个对象,可能是跟着多个对象
如:
由线和点构成的一个结构,操作对象像一张网一样互相连接在一起。
操作:找一条最短路径
操作对象:ABCD这些个路线点。
操作关系:网状关系
综上所述
数据结构
:研究非数值计算的程序设计中计算机的操作对象以及他们之间的关系和操作的学科。数据
:
能输入计算机且能被计算机处理的各种符号的集合
包括:
数据元素:
比如说这样一个学生表,假设某个同学转学了,那么是对那个同学的那一行进行整体的删除,这样一个学生的相关信息就是作为整个数据的某一个整体来操作 ,每一行学生信息就是组成数据的数据元素
数据项:
数据对象:
数据元素与数据对象
结构
(比如:线性、非线性)。数据结构包括
:
逻辑结构:
物理结构(存储结构):
逻辑结构与存储结构的关系:
划分方法1
:
线性结构
非线性结构
集合结构:结构中的数据元素之间处理同属于一个集合的关系之外,没有其他任何的关系。
线性结构:结构中的数据元素之间存在着一对一的线性关系。
树形结构:结构中的数据元素之前存在着一对多的层次关系
图状结构或网状结构:结构中的数据元素之间存在着多对多的任意关系。
顺序存储结构
链式存储结构
像有根链条连起来一样,前一个元素存着下一个元素的地址,不管你存在哪里,等用到你的时候都可以用前一个元素存着的下个元素的地址找到下一个元素
一组性质相同的值得集合,以及定义于这个值集合上的一组操作的总称
内置类型:int、double、char这些。
自定义类型:数组、enum、struct、union这些。
还有指针、void类型的指针。
数据类型的作用
一个数学模型以及定义在刺数学模型上的一组操作。
抽象数据类型
抽象数据类型的形式定义
定义一个圆
注:这是个伪代码,要实现得转成各类语言对应格式。
简单用代码弄一下
#include
#include
void Circle(int* C,int r,int x,int y)//数据对象
{
C[0]= r;
C[1]= x;
C[2]= y;
}
double Area(int* C)
{
return 3.14 * pow(C[0],2);
}
double Circumference(int* C)
{
return 2 * 3.14 * C[0];
}
int main()
{
int C[3]= {0},r,x,y;
int i;
printf("请输圆的半径及xy的坐标");
scanf ("%d %d %d",&r,&x,&y);
Circle(C,r,x,y);
printf("圆的面积是:%lf\n",Area(C));
printf("圆的周长是:%lf\n",Circumference(C));
return 0;
}
请输圆的半径及xy的坐标 3 3 3
圆的面积是:28.260000
圆的周长是:18.840000
对特定问题求解方法和步骤的一种描述,它是
指令
的有限序列
。其中每个指令表示一个或多个操作。
描述代码该怎样实现
例如:描述怎么实现求一元二次方程的根
算法与程序
算法特性
算法效率
算法时间效率可以用依据改算法编制的程序在计算机上执行所消耗的时间来度量。
两种度量方法:
事前分析方法
乘积
。
例如:
for(i = 1;i <= n;i++)//执行n + 1次
{
for(j = 1;j <= n;j++)//执行n(n + 1)次
{
c[i][j] = 0;//n * n次
for(k = 0;k < nk++)//执行n * n(n +1)次
{
c[i][j] = c[i][j]+a[i][k] * b[k][j];//n * n * n次
}
}
}
- 所有语句的执行次数加起来就是时间频度之和。
- 把算法所耗费的时间定义为**该算法中每条语句的频度之和**。
-则上述算法的时间消耗为T(n)为:T(n) = 2n ^ 3 + 3n ^ 2 + 2n + 1(这种方法很麻烦)
为了方便比较不同算法的时间效率,我们仅比较他们的数量级
例如:两个不同的算法,时间消耗分别是:
若有若干辅助函数 f(n),使得 n 趋近于无穷大,T(n) / f(n)的极限值为不等于零的常数,则称 f(n) 是 T(n)的同数量级函数(同阶,次方相同)。记作**T(n) = O(f(n))
,称O(f(n))为算法的渐进时间复杂度**(O是数量级的符号),简称时间复杂度。
一般情况下,不必计算所有操作的执行次数,而只考虑算法中的基本操作执行的次数,它是问题规模n的某个函数,用T(n)表示
算法中基本语句重复执行的次数
是 问题规模
n的某个函数f(n),算法的时间量度记作:T(n) = O(f(n))
基本语句重复执行的次数
问题规模
n越大算法的执行时间就越长
举个栗子:
int x = 0,y = 0;//执行1次
for(int k = 0;k < n;k++)//这条for语句执行n + 1次
{
x++ ;//这个循环体执行n次
}
for(int i = 0;i < n;i++)//执行n + 1次
{
for(int j = 0;j < n;j++)//外层循环每执行1次这个for循环就要执行n + 1次
//所以这个for循环要执行 n * (n + 1)次
y++ ;//执行n * n 次
}
void exam(float x[][],int m,int n)
{
float sum[];
for(int i = 0;i < m;i++)
{
sum[i] = 0.0 ;
for(int j = 0;j < n;j++)
{
sum[i] += x[i][j];//这条语句嵌套最深,所以复杂度最高,执行m * n 次
//表示成函数就是f(n) = m * n,数量级为T(n) = O(m * n)
}
}
for(i = 0;i < m;i++)
{
cout << i << ":"<< sum [i]<< endl;
}
}
N * N 矩阵相乘
for(i = 1;i <= n;i++)
{
for(j = 1;j <= n;j++)
{
c[i][j] = 0;
for(k = 1;k <= n;k++)
{
c[i][j] = c[i][j] + a[i][k] * b[k][j];//这条语句执行最多
//f(n) = n * n * n,T(n) = O(n^3)
}
}
}
f(n) = n * n * n ,时间复杂度 T(n) = O(n^3)
for(i = 1;i <= n;i++)
{
for(j = 1;j <= i;j++)
{
for(k = 1;k <= j;k++)
{
x = x + 1;//T(n) = O(n^3)
}
}
}
第二重是j到i,j是变量,相当于1+2+3+…+i等于i*(i+1)/2,第一层同理。
算法时间复杂度计算
有的情况下,算法中基本操作重复执行的次数还随问题的
输入数据集
不同而不同
【例】顺序查找,在数组a[i]中查找值等于 e 的元素,返回其所在位置。
for(i = 0;i < n;i++)
{
if(e == a[i])
{
return i + 1;
//找到,则返回是第几个元素
}
}
return 0;
最好的情况是第一个元素就是要查找的元素,最坏则是最后一个元素,循环体执行的次数和 e 实际放的位置有关
最好情况:执行 1 次
最坏情况:执行 n 次
平均时间复杂度:O(n)
一般总是在考虑最坏情况下的时间复杂度,以保证算法的运行时间不会比它更长。
对于复杂的算法,可以将它分成几个容易估算的部分,然后用大O加法法则和乘法法则,计算算法的时间复杂度。
当 n 取得很大时,指数时间算法和多项式时间算法在所需时间上非常悬殊。
时间复杂度 T(n) 按数量级递增顺序为:
空间复杂度:算法所需存储空间的度量。
S(n) = O(f(n))
算法要占据的空间
辅助空间
【例】将一维数组 a 中的n个数逆序放到原数组中
int n,i,a[10] = {1,2,3,4,5,6,7,8,9,10};
int sz = sizeof(a)/sizeof(a[0]);
printf("你要逆序几个数:");
scanf ("%d",&n);
for(i = 0;i < n;i++)
{
int t = a[i];
a[i] = a[sz -1-i];
a[sz -1- i] = t;
}
for(i = 0;i < sz;i++)
{
printf("%d ",a[i]);
}
putchar('\n');