一、基本定义
1、数据
数据:是对客观事物的符号表示,在计算机科学中是指所有能输入到计算机中并被计算机程序处理的符号的总称。
数据结构:是相互之间存在一种或多种特定关系的数据元素的集合。
数据元素:数据的基本单元
数据项:一个元素可由若干个数据项组成,是数据的不可分割的最小单位。
数据对象:性质相同的数据元素的集合,是数据的一个子集。
数据元素都不是孤立存在的,它们之间存在某种关系,称为结构。
2、根据数据元素之间关系的不同特性,有4种基本结构:
1)集合:除了‘同属于一个集合’关系外,别无其它关系;
2)线性结构:一对一关系;
3)树形结构:一对多关系;
4)图状结构或网状结构:多个对多个关系;
3、数据元素之间的关系在计算机中有两种不同的表示方法:顺序映像和非顺序映像。
并由此得到两种不同的存储结构:顺序存储结构(相对位置)和链式存储结构(指示元素存储地址的指针)。顺序和链路在一种存储算法中只能用一种。
顺序映像特点:借助元素在存储器中的相对位置来表示数据元素之间的逻辑关系;
非顺序映像特点:借助指示元素存储地址的指针来表示数据元素之间的逻辑关系。
4、数据类型:用以刻画(程序)操作对象的特征。是一个值的集合和定义在这个值集上的一组操作的总称。
1)抽象数据类型(abstract data type,简称ADT):指一个数学模型以及定义在该模型上的一组操作。
抽象数据类型表示:可用三元组(D,S,P),D是数据对象,S是D上的关系集,P是对D的基本操作集。
定义抽象数据类型:
ADT 抽象数据类型名{
数据对象:<数据对象的定义>
数据关系:<数据关系的定义>
基本操作:<基本操作的定义>
}ADT 抽象数据类型名
数据对象和数据关系的定义用伪码描述。
基本操作的定义格式为:对于引用参数,定义前加&,调用时不要加&。
基本操作名(参数表)
初始条件:<初始条件描述>
操作结果:<操作结果描述>
数据结构的表示(存储结构)用类型定义(typedef)描述。
status是函数的类型,其值是函数结果状态代码。typedef int status; Elemtype:数据元素类型约定为Elemtype。
基本操作的算法:
函数类型 函数名(函数参数表){
//算法说明
语句序列
}//函数名
输入输出等语句:
scanf([格式串],变量1,...,变量n);
printf([格式串],表达式1,...,表达式n);
floor(表达式) //求不足整数值
ceil(表达式) //求进位整数值
eof(文件变量)或eof //判定文件结束
eoln(文件变量)或eoln //判定行结束
基本操作的实现:
Status InitTriplet(Triplet &T,ElemType v1,ElemType v2,ElemType v3){
//构造三元组T,依次置T的3个元素的初始值为v1,v2,v3。
T=(ElemType *) malloc(3*sizeof(ElemType)); //分配3个元素的存储空间
if (!T) exit(OVERFLOW); //分配存储空间失败
T[0]=v1; T[1]=v2; T[2]=v3;
return OK;
}//InitTriplet
Status DestroyTriplet(Triplet &T){
//销毁三元组T
free(T); T=NULL;
return OK;
}//DestroyTriplet
Status Get(Triplet T,int I,ElemType &e){
//1≤I≤3,用e返回T的第i元的值。
if(i<1 || i>3)return ERROR;
e=T[i-1];
return OK;
}//Get
5、算法algorithm
是对特定问题求解步骤的一种描述,是指令的有限序列,其中每一条指令表示一个或多个操作;
算法具有5个特性:有穷性,不确定性,可行性,输入,输出。
算法设计的要求:正确性,可读性,健壮性,效率与低存储量需求;
算法效率的度量:时间复杂度T(n)=O(f(n)) //表示随问题规模n的增大,算法执行时间的增长率和f(n)的增长率相同
算法的存储空间需求:空间复杂度S(n)=O(f(n))
算法的执行时间=∑原操作(i)的执行次数
二、线性表
1、线性表的类型定义
线性结构的特点:在数据元素的非空有限集中,(1)存在唯一的一个被称作“第一个”的数据元素;(2)存在唯一的一个被称作“最后一个”的数据元素;(3)除第一个之外,集合中的每个数据元素均只有一个前驱;(4)除最后一个之外,集合中每个数据元素均只有一个后继。
基本线性结构有:线性表、栈、队列、串、数组、广义表、树、二叉树、图等。
抽象数据类型的线性表的定义:
ADT List{
数据对象:D={ai|ai属于ElemSet,i=1,2,...n,n≥0} //其中i和i-1为下标
数据关系:R1={<ai-1,ai>| ai-1,ai属于D,i=2,...n}
基本操作:
InitList(&L)
操作结果:构造一个空的线性表L。
}ADT List
算法:
void union(List &La,List Lb){
//将所有在线性表Lb中但不在La中的数据元素插入到La中
La_len=ListLength(La),Lb_len=ListLength(Lb); //求线性表的长度
for(i=1;i<Lb_len;i++){
GetElem(Lb,i,e); //取Lb中第i个元素赋给e
if(!LocateElem(La,e,equal))ListInsert(La,++La_len,e);
//La中不存在和e相同的数据元素,则插入之。
}
}//union
时间复杂度O(La_len*Lb_len)
void MergeList(List La,List Lb,List &Lc){
//已知线性表La和Lb中数据元素按值非递减排列
//归并La和Lb得到新的线性表Lc,Lc的数据元素也按值非递减排列
InitList(Lc);
i=j=1;k=0;
La_len=ListLength(La);Lb_len=ListLength(Lb);
while((i<La_len)&&(j≤Lb_len)){//La和Lb均非空
GetElem(La,i,ai);GetElem(Lb,j,bj);
if(ai<bj){ListInsert(Lc,++k,ai);++i;}
else{ListInsert(Lc,++k,bj);++j;}
}
while(i≤La_len){
GetElem(La,i++,ai);ListInsert(Lc,++k,ai);
}
while(j≤Lb_len){
GetElem(Lb,j++,bj);ListInsert(Lc,++k,bj);
}
}//MergeList
时间复杂度O(La_len+Lb_len)
2、线性表的顺序表示和实现
线性表的顺序表示指:用一组地址连续的存储单元依次存储线性表的数据元素。以所占的第一个单元的存储地址作为数据元素的存储地址。
弱点:在做插入或删除操作时,需移动大量元素。
//----------线性表的动态分配顺序存储结构----------
#define LIST_INIT_SIZE 100 //线性表存储空间的初始分配量
#define LISTINCREMENT 10 //线性表存储空间的分配增量
typedef struct { //typedef关键字,struct结构体
ElemType *elem; //存储空间基址,初始地址。数组指针elem指示线性表的基地址
int length; //当前长度
int listsize; //当前分配的存储容量(以sizeof(ElemType)为单位)
}//SqList;
Status InitList_Sq(SqList &L){
//构造一个空的线性表L
L.elem=(ElemType *)malloc(LIST_INIT_SIZE*sizeof(ElemType)); //C语言的malloc相当于C++的new,直接分配地址。
if(!L.elem) exit(OVERFLOW); //存储分配失败
L.length=0; //空表长度为0
L.listsize=LIST_INIT_SIZE; //初始存储容量
return OK;
}//InitList_Sq