数据结构C语言版笔记 第一章
参考清华大学出版社的《数据结构(C语言版)》
第一章 绪论
1.1什么是数据结构
1.1.1数据(Data)
(1)对客观事物的符号描述,能输入到计算机中并被计算机程序处理的符号的总称;
(2)能被计算机识别、储存和加工处理的信息的载体。
例如:数字,字母,图像,视频,表格。
1.1.2数据元素(Data Element)
数据元素是组成数据的基本单位,是数据集合的个体,再计算机中通常作为一个整体进行考虑和处理。
数据项:一个元素可由若干个数据项组成
数据项是数据的不可分割的最小单位。
1.1.3数据结构(Data Structure)
数据结构是指相互之间存在一种或多种特定关系的数据元素集合,
结构(Structure):数据元素相互之间的关系。
在形式上可用二元组表示:
Data_Structure = (D,S)
D:数据元素的有限集
S:D上关系的有限集
D上的一个关系r是序偶的集合,对于r中任一序偶<x,y>(x,y属于D),我们称序偶的第一结点为第二结点的直接前驱结点(简称前驱结点),称第二结点为第一结点的直接后继结点(简称后继结点)。
<>表示有向关系,()表示无向关系。
1.1.4逻辑结构图:
可将数据结构用图像形象的表示出来,每个结点对应一个数据元素,两个结点之间的连线对应着关系中的一个序偶。
1.2数据结构的内容
1.2.1逻辑结构:
数据元素之间的关系;
逻辑结构可以看作是从具体问题抽象出来的数学模型。
1.2.2逻辑结构类型的分类
按照逻辑关系的不同特性分类:
(1)集合:同属于一个集合
(2)线性结构:一对一
(3)非线性结构:
1、树型结构:一对多
2、图型结构:多对多
1.2.3逻辑结构类型
(1)线性结构:
特点:开始结点和终端结点都是唯一的,除了开始结点和终端结点外,其余结点都有且仅有一个很前驱结点,有且仅有一个后继结点。
顺序表就是典型的线性结构。
(2)非线性结构:
树型结构特点:每个结点最多只有一个前驱,可以有多个后继结点。简称为“树”。
图型结构特点:每个结点可能没有开始结点和终端结点,也可能有多个,简称为“图”。
1.2.4存储结构(物理结构)
即逻辑结构在计算机中的实现,包括数据元素的表示和关系的表示。
(1)顺序存储结构
用顺序存储法存放学生表的结构体定义
struct Stud{
int no; /*学号*/
char name[8]; /*姓名*/
char sex[2]; /*性别*/
char class[4]; /*班号*/
} Studs[7]={
{1,"张斌","男","9901"},
...
{5,"王萍","女","9901"}
};
(2)非顺序存储结构
用链式存储法存放学生表的结构体定义
typedef struct node
{
int no;
char name[8];
char sex[2];
char class[4];
struct node*nest; /*指向下一个学生的指针*/
} StudType;
链式存储法的缺点:
1存储空间占用大;
2无法随机访问;
链式存储法的优点:
1便于修改。
(3)索引存储结构
(4)散列存储结构
逻辑结构与存储结构的关系
(1)存储结构是逻辑结构用计算机语言的实现;
(2)如何用计算机语言表示数据元素之间的各种关系。
存储结构是逻辑结构的映像与元素本身的映像;逻辑结构是数据结构的抽象;存储结构是数据结构的实现。
1.2.5 数据的运算
就是施加于数据的操作,如查找、添加、修改、删除等。例如:线性表的初始化、查找、插入、修改、删除。
(1)算法的设计取决于选定的数据(逻辑)结构,而算法的实现依赖于采用的存储结构。
(2)抽象运算定义在逻辑结构上,而实现在存储结构上。
1.2.6数据类型——抽象数据类型
抽象数据类型指的是用户进行软件设计时从问题的数学模型抽象出来的逻辑数据结构和运算,不考虑计算机的具体存储结构和运算的具体实现算法。
一个抽象数据类型的模块通常包括定义、表示和实现。
抽象数据类型是一个三元组(D,S,P)
其中:D是数据对象
S是D上数据关系的有限集
P是对D的基本操作的有限集
ADT 抽象数据类型名
{
数据对象的定义
数据关系的定义
基本操作的定义
} ADT 抽象数据类型名
通常用伪码描述
例如,抽象定义”复数“
ADT Complex{
D={e1,e2|e1,e2属于RealSet}
R1={<e1,e2>|e1是复数的实数部分,|e2是复数的虚数部分}
AssignComplex(&Z,v1,v2)
DestoryComplex(&Z)
GetReal(Z,&RealPart)
GetImag(Z,&ImagPart)
Add(z1,z2,&sum)
}ADT Complex
/*具体用处参考课本*/
ADT有两个重要特征:
数据抽象;数据封装
抽象数据类型的表示和实现
需要通过固有数据类型(高级编译语言中已实现的数据类型)来实现。
例如:
//存储结构的定义
typedef struct{
float realpart;
float imagpart;
}complex;
//基本操作的函数原型说明
void AssignComplex(complex &Z,float realval,float imagval);
//构造复数Z,其实部和虚部分别赋以参数
//realval和imagval的值
float GetReal(complex Z);
//返回实部值
float GetImag(complex Z);
//返回虚部值
void add(complex z1,complex z2,complex &sum);
//sum函数返回两个复数的和
//基本操作的实现
void add(complex z1,complex z2.complex &sum){
sum.realpart=z1.realpart+z2.realpart;
sum.imagpart=z1.imagpart+z2.imagpart;
}
{其他省略}
1.3算法
1.3.1算法(Algorithm)的定义
算法是规则的有限集合,是为解决特定的问题而规定的一系列操作。
1.3.2算法的特性
(1)有穷性:有限步骤之内正常结束,不能形成无限循环。
(2)确定性:算法中的每一个步骤必须有确定含义,无二义性。
(3)可行性:原则上能精确进行,操作可通过已实现的基本运算执行有限次而完成。
(4)输入:有多个或0个输入。
(5)输出:至少有一个或多个输出。
其中最基本的是有限性、确定性和可行性。
以下是错误的!
void exam1()
{
n=2;
while(n%2==0)
n+=2;
printf("%d\n",n);
}
(违背了有穷性)
void exam2()
{
y=0;
x=3/y;
printf("%d,%d\n",x,y);
}
(违背了可行性)
算分和数据结构是两个不可分割的统一体
(1)程序=数据结构+算法
(2)数据结构通过算法实现操作
(3)算法根据数据结构设计程序
算法设计的要求:
(1)正确性 正确反映需求(通过测试)
(2)可读性 有助于理解、调试和维护
(3)健壮性 完备的异常和出错处理
(4)高效率与低存储的需求 时间、空间的要求
1.4算法描述的工具
描述算法的方法:
——自然语言
——高级程序设计语言
——类语言
*举例:两个数据a,b交换空间
自然语言:交换a,b的存储空间
高级语言:{x=a,a=b;b=x;}
类语言:a<–>b; //交换空间
1.5对算法作性能评价
衡量算法效率的方法主要有两大类:
——事后统计:利用计算机的时钟;
——事前分析估算:用高级语言编写的程序运行的时间主要取决于:
—算法;
—问题规模;
—使用语言;
—编译程序;
—机器;
通常,从算法中选取一种对于研究的问题来说是基本操作的原操作,一改基本操作重复执行的次数作为算法执行的时间度量。
例:
x=x+1;
//a
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
x=x+1;
//b
for(i=1;i<=n;i++)
x=x+1;
//c
基本操作重复执行的次数分别是1,n,n^2。
设算法的问题规模为n;
频度:语句重复执行的次数成为该语句的频度,记f(n)。
对算法各个基本操作的频度求和,便可得算法的时间复杂度。实际中取最大频度数量级。
时间复杂度:T(n)=O(maxlevel(f(n)))
(1)x=x+1;其时间复杂度为O(1),我们称之为常量阶;
(2)for(i=1;i<=n;i++)x=x+1;其时间复杂度为O(n),我们称之为线性阶;
(3)for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
x=x+1;
其时间复杂度为O(n^2),我们称之为平方阶;
此外还有对数阶,指数阶等。
常见的时间复杂度,按数量级递增排序
常数阶 O(1)
对数阶 O(log2(n))
线性阶 O(n)
线性对数阶 O(nlog2(n))
平方阶 O(n^2)
立方阶 O(n^3)
…………
K次方阶 O(n^k)
指数阶 O(2^n)
最坏时间复杂度
有时,算法中基本操作重复执行的次数随问题的输入不同而不同,通常分析最坏情况下的时间复杂度。
算法的空间复杂度
关于算法的存储空间要求,类似于算法的时间复杂度,我们采用空间复杂度作为算法所需存储空间的量度,记作:
S(n)=O(f(n))