目录
1.1什么是数据结构
一、名词术语
二、数据结构的定义
存储结构:
三.数据结构课程研究的主要内容
1.2 抽象数据类型
一、抽象数据类型
二、抽象数据类型的表示与实现
1.3 算法及其描述
一、算法及其性质
二、算法的描述
1.4 算法分析
本章内容小结
数据:描述客观事物的数字、字符以及一切能够输入到计算机中,并且能够被计算机程序处理的符号的集合
数据元素:数据这个集合中的一个一个的元素
数据对象:具有相同特性的数据元素的集合。
结构:数据元素之间具有的关系(联系)。
1.数据元素之间的联系称之为结构,数据结构就是具有结构的数据元素的集合。
2.数据结构是一个二元组 Data-Structure=( D, R ),其中,D是数据元素的有限集合,R是D上的关系的集合
1.顺序存储结构:用一组地址连续的存储单元依次存放数据元素,数据元素之间的逻辑关系通过元素的地址直接反映
2.链式存储结构:用一组地址任意的存储单元依次存放数据元素,数据元素之间的逻辑关系通过指针间接地反映
3.索引存储结构:
构造原理:利用数据元素的索引关系来确定数据元素的存储位置,由数据元素本身与索引表两部分组成。
特点:如查找、插入和删除等操作的时间效率较高,但存储空间开销较大。
4.散列存储结构:
构造原理:通过事先准备好的散列函数关系与处理冲突的方法来确定数据元素的存储位置。
特点:诸如查找、插入和删除等操作的时间效率较高,主要缺点是确定好的散列函数比较困难。
1.研究数据元素之间的客观联系。(逻辑结构)
2.研究具有某种逻辑关系的数据在计算机存储器内的存储方式。(存储结构)
3. 研究如何在数据的各种关系(逻辑的和物理的)的基础上对数据实施一系列有效的基本操作。逻辑结构逻辑结构存储结构存储结构算法。(算法)
定义:在一种程序设计语言中,变量所具有的数据种类
FORTRAN语言:整型、实型、和复数型
C语言:
基本数据类型: char int float double void
构造数据类型:数组、结构体、共用体、文件
数据类型是一组性质相同的值的集合, 以及定义于这个集合上的一组运算的总称
抽象数据类型
(ADTs: Abstract Data Types)
更高层次的数据抽象
由用户定义,用以表示应用问题的数据模型
由基本的数据类型组成, 并包括一组相关的操作
抽象数据类型可以用以下的三元组来表示:
ADT = (D,S,P)
数据对象 D上的关系集 D上的操作集
ADT抽象数据类型名{
数据对象:<数据对象的定义>
数据关系:<数据关系的定义>
基本操作 :<基本操作的定义>
} ADT抽象数据类型名
抽象数据类型可以通过固有的数据类型(如整型、实型、字符型等)来表示和实现。
它有些类似C语言中的结构(struct)类型,但增加了相关的操作
教材中用的是类C语言(介于伪码和C语言之间)作为描述工具
(1)预定义常量及类型
//函数结果状态代码
#define OK 1
#define ERROR 0
#define OVERFLOW -2
// Status是函数返回值类型,其值是函数结果状态代码。
typedef int Status;
(2)数据元素被约定为ElemType 类型,用户需要根据具体情况,自行定义该数据类型。
(3)算法描述为以下的函数形式:
函数类型 函数名(函数参数表)
{
语句序列;
}
1.算法的定义
(1)算法是用来解决某个特定课题的指令的集合。
(2)算法是由人们组织起来准备加以实施的一系列有限的基本步骤。
(3)算法是一组解决问题的清晰指令,它能够对符合一定规范的输入,在有限的时间内获得所需要的输出。
算法不是问题解决的答案,而是获得答案的过程。
2.算法的性质
一个完整的算法应该具有下面五个基本特性:
输入:由算法的外部提供n≥0个有限量作为算法的输入
输出:由算法的内部提供n>0个有限量作为算法的输出
又穷性:算法必须在有限的步骤内能够结束
确定性:组成算法的每一条指令必须有清晰明确的含义
可行性:算法的每一条指令必须具有可执行性
1.采用自然语言来描述
问题:求两个正整数M与N的最大公因子
(1)M除以N,将余数送中间变量R;
(2) 测试余数R是否等于零?
a) 若R等于零,求得的最大公因子为当前N的值, 算法到此结束。
b) 若R不等于零,则将N送入M,将R送N, 重复算法的(1)和(2)。
2.采用程序流程图的形式来描述
3. 设计一种既脱离某种具体的程序设计语言,又具有各种程序设计语言的共同特点的形式化语言来描述。
类Pascal语言(早期)
类C语言(常用)
类C++语言
类Java语言
4. 采用某种具体程序语言来描述
int COMFACTOR( int M, int N )
{
int R;
while( 1 ){
R=M % N;
if(R==0)
return N;
M=N;
N=R;
}
}
算法分析 是指对算法质量优劣的评价(目的:改进算法质量;前提:算法必须正确)
时空效率高的算法才是一个好的算法,它常常是不懈努力和反复修正的结果
除正确性外,通常从三个方面分析一个算法:
依据算法编写的程序在计算机中运行时间多少的度量,称之为时间复杂度。反映算法运行的快慢
依据算法编写的程序在计算机中占存储空间多少的度量,称之为空间复杂度。反映算法需要的额外空间的多少
其他方面。如算法的可读性、可移植性以及易测试性的好坏。
算法的效率的度量
算法效率:用依据该算法编制的程序在计算机上执行所消耗的时间来度量
1.事后统计:
利用计算机内的计时功能,不同算法的程序可以用一组或多组相同的统计数据区分
缺点:
必须先运行依据算法编制的程序
所得时间统计量依赖于硬件、软件等环境因素,掩盖算法本身的优劣
2.事前分析估计:
一个高级语言程序在计算机上运行所消耗的时间取决于:依据的算法选用何种策略问题的规模,程序语言,编译程序产生机器代码质量,机器执行指令速度
同一个算法用不同的语言、不同的编译程序、在不同的计算机上运行,效率均不同,——使用绝对时间单位衡量算法效率不合适
时间复杂度
一个程序在计算机中运行时间的多少与诸多因素有关,其中主要有:
1.问题的规模(几乎所有算法的时间效率都与问题的规模有关)
2.编译程序功能的强弱以及所产生的机器代码质量的优劣。
3.机器执行一条指令的时间长短。
4.程序中那些关键语句的执行次数。(对算法运行时间贡献最大的语句,与1相关)
频度统计法
以语句执行的次数的多少作为算法时间度量的分析方法成为频度统计法
一条语句的频度是指该语句被执行的次数,而整个算法的频度是指算法中所有语句的频度之和
时间复杂度的渐进表示法
算法中基本语句重复执行的次数(算法中重复执行次数和算法的执行时间成正比的语句;对算法运行时间的贡献最大)是问题规模n(
n越大算法的执行时间越长 排序:n为记录数;矩阵:n为矩阵的阶数;多项式:n为多项式的项数;集合:n为元素个数;树:n为树的结点个数;图:n为图的顶点数或边数)的某个函数f(n),算法的时间量度记作:T(n)=O(f(n))
表示随着n的增大,算法执行的时间的增长率和f(n)的增长率相同,称渐近时间复杂度。
数学符号“O”的定义为:
若T(n)和f(n)是定义在正整数集合上的两个函数,则T(n) = O(f(n))表示存在正的常数C和n0,使得当n≥n0时都满足0≤T(n)≤Cf(n)。
例1:求两个n阶矩阵的乘积 T(n) = O(n3)
#define M 1000
void MATRIX( int A[ ][M], int B[ ][M], int C[ ][M], int n)
{
int i, j, k;
for(i=0;i
例2:n * n阶矩阵加法:T(n) = O(n2)
for( i = 0; i < n; i++)
for( j = 0; j < n; j++)
c[i][j] = a[i][j] + b[i][j];
分析算法时间复杂度的基本方法
找出语句频度最大的那条语句作为基本语句
计算基本语句的频度得到问题规模n的某个函数f(n)
取其数量级用符号“O”表示
时间复杂度是由嵌套最深层语句的频度决定的
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]; //f(n)=m*n;T(n) = O(m*n)
}
for ( i = 0; i < m; i++ )
printf(“%d : %d\n”,i,sum [i]);
}
例3:T(n) = O(n3)
for( i=1; i<=n; i++)
for (j=1; j<=i; j++)
for (k=1; k<=j; k++)
x=x+1;
定理1.1
若f(n)=amnm+am-1nm-1+¼+a1n+a0是m次多项式,则T(n)=O(nm)。
例4:分析以下程序段的时间复杂度 T(n) =O( logn)
i=1; ①
while(i<=n)
i=i*2; ②
渐进空间复杂度
•空间复杂度:算法所需存储空间的度量,记作: S(n)=O(f(n))
其中n为问题的规模(或大小)
算法要占据的空间
Ø算法本身要占据的空间,输入/输出,指令,常数,变量等
Ø算法要使用的辅助空间
例5:将一维数组a中的n个数逆序存放到原数组中
【算法1】 S(n) = O(1) 原地工作
for(i=0;i
【算法2】 S(n) = O(n)
for(i=0;i