1.数据结构在学什么?
如何用程序代码把现实世界的问题信息化?
如何用计算机高效地处理这些信息从而创造价值?
2.数据结构的基本概念
数据:是客观事物的符号表示(在计算机科学中指的是所有能输入到计算机中并被计算机程序处理的符号的总称)
数据元素:是数据的基本单元,在程序中通常作为一个整体来进行考虑和处理。
一个数据元素可由若干个数据项组成。
数据项是数据的不可分割的最小单位。
数据项是对客观事物某一方面特性的数据描述。
数据结构(Data Structure):是指相互之间具有(存在)一定联系(关系)的数据元素的集合。
数据对象:是具有相同性质的数据元素的集合,是数据的一个子集
3.信息的表示:数据结构(线性表、队列等)
信息的处理:算法(排序和查找)
逻辑结构:数据元素之间逻辑关系的描述
存储结构:数据元素在计算机中的存储及其逻辑关系的表现称为存储结构或物理结构
数据操作:对数据要进行的运算。
应用:应用场景有哪些或者具体的用途
4.算法
解决问题的过程或者步骤
算法思想:如何想
核心代码:怎么做
算法分析:时间复杂度和空间复杂度
手动执行过程:作何解
算法外延:有何用
5.逻辑结构
数据元素之间的关系可以是元素之间代表某种含义的自然关系,也可以是为处理问题方便而人为定义的关系,这种人为定义的”关系“称为数据元素之间的逻辑关系,相应的结构称为逻辑结构/概念结构。
6.逻辑结构有四种基本类型
集合:结构中的数据元素除了”同属于一个集合“外没有其他关系。
线性结构:结构中的数据元素之间存在一对一的关系
树型结构:结构中的数据元素之间存在一对多的关系
图状结构或网状结构:结构中的数据元素之间存在多对多的关系。
备注:逻辑结构与数据元素本身的形式、内容无关
逻辑结构与数据元素的相对位置无关
逻辑结构与所含结点个数无关
逻辑结构与计算机无关。
7.物理结构
数据结构在计算机中存储的形式叫做物理结构或者存储结构。
顺序结构:数据元素在内存中按序连续存储,用数据元素在存储器中的相对位置来表示数据元素之间的逻辑关系。
注:在C语言中,通常用一维数组表示顺序存储结构;数据元素存放的地址是连续的;随机存取表中元素;插入和删除操作需要移动元素。
链接结构:在每一个数据元素中增加存放另一个元素地址的指针,用该指针来表示数据元素之间的逻辑结构关系。
注:用结构体类型表示链式存储结构。
比顺序存储结构的存储密度小(每个节点都由数据域和指针域组成,所以相同空间内假设全存满的话顺序比链式存储更多)
逻辑上相邻的节点物理上不比相邻
插入、删除灵活(不必移动节点、只要改变节点中的指针)
查找结点时链式存储要比顺序存储慢
索引结构:除建立存储结点信息外,还建立附加的索引标来标识结点的地址。索引表由若干索引项组成。
注:索引存储结构是用结点的索引号来确定结点存储地址。优点时检索速度快,缺点是增加了附加的索引表,会占用较多的存储空间。
散列存储方法:散列存储,又称hash存储,是一种试图将数据元素的存储位置与关键码之间建立确定对应关系的查找技术。
8.算法和复杂度计算
算法:是对特定问题求解方法(步骤)的一种描述,是指令的有限序列,其中每一条指令表示一个或多个操作。算法可以有三种表示形式:伪代码、自然语言和流程图。
有穷性、确定性、可行性、输入、输出
算法评价:正确性、可读性、健壮性、通用性。
效率与存储量需求:效率指的是算法执行的时间;存储量需求指算法执行过程中所需要的最大存储空间。一般地,这两者与问题的规模有关。
9.算法效率的度量
算法中基本操作重复执行的次数是问题规模n的某个函数,其时间量度记作T(n)=O(f(n)),称作算法的渐进时间复杂度,简称时间复杂度。
一般地,常用最深层循环内的语句中的原操作的执行频度(重复执行的次数)来表示。
{
++x;
s=0;
}
将x自增看成是基本操作,则语句频度为1,时间复杂度为O(1)常量阶
将s=0也看成是基本操作,则语句频度为2,时间复杂度为O(1)
for(i=1;i<=n;++i){
++x;
s+=x;
}
语句频度为:2n,其时间复杂度为:O(n),即为线性阶。
for(i=1;i<=n;i++){
for(j=1;j<=n;++j){
++x;
s+=x;
}
}
语句频度为2n平方,其时间复杂度为,即为平方阶。
//两个n阶方阵的乘法
for(i=1;i<=n;++i){
for(i=1;i<=n;++j){
c[i][j]=0;
for(k=1;k<=n;++k){
c[i][j]+=a[i][k]*b[k][j];
}
}
}
由于是一个三重循环,每个循环从1到n,总次数为n的三次方,时间复杂度为T(n)=O(n的三次方) 立方阶
对数阶:下列程序段的时间复杂度是
count=1;
while(count<N)
count*=2;
递归:
冒泡排序:
void bubble_sort(int a[],int n){
change=false;
for(i=n-1;change=TRUE;i>1&&change;--i){
for(j=0;j<i;++j)
if(a[j]>a[j+1])
{
a[j]←→[j+1];change=TRUE;
}
}
}
最好情况:0次
最坏情况:1+2+3+...+n-1=n(n-1)/2
平均时间复杂度为:O(n²)
算法的时间复杂度除了与问题的规模有关,还与问题待处理数据的初始状态有关。
10.空间复杂度的度量
是指算法编写成程序后,在计算机中运行时所需存储空间大小的度量。记作:S(n)=O(f(n))其中:n为问题的规模或大小。
程序运行时存储空间一般包括三个方面:1. 指令常数变量所占用的存储空间;2.输入数据所占用的存储空间;辅助(存储)空间。
某算法的空间复杂度为O(1):则该算法执行所需辅助空间大小与问题规模n无关。
for(i=1;i<=n;++i){
for(j=1;j<=n;++j){
++x;
s+=x;
}
}
//临时变量为:i,j,s,x;空间复杂度为:O(1),即常量阶
11.线性表
线性结构是最常用、最简单的一种数据结构。而线性表是一种典型的线性结构。其基本特点是线性表中的数据元素是有序且是有限的。
线性表中的结点可以是单值元素(每个元素只有一个数据项)
线性表中的结点可以是记录型元素,每个元素含有多个数据项,每个项称为结点的一个域,每个元素有一个可以唯一标识每个结点的数据项组,称为关键字。
11.1线性表的抽象数据类型定义
ADT List{
数据对象:D={ai|ai∈ElemSet,i=1,2,..,n, n>=0}
数据关系:R={<ai-1,ai> | ai∈Di,i=2,3,...,n}
基本操作:
InitList(&L) 操作结果:构造一个空的线性表L
ListLength(L) 初始条件:线性表L已存在
操作结果:若L为空表,则返回TRUE,否则返回FALSE
GetElem(L,i.$e) 初始条件:线性表L已存在,1<=i<=ListLength(L)
操作结果:用e返回L中第i个数据元素的值
ListInsert(L,i,&e) 初始条件:线性表L已存在,1<=i<=ListLength(L)
操作结果:在线性表L中的第i个位置插入元素e
}ADT List
11.2结构体
数组具有随机存取的特性,因此借助数组来描述顺序表,除了用数组来存储线性表的元素之外,顺序表还应该有表示线性表的长度属性,用结构体类型来定义顺序表类型。
#define MAXSZIE 100//数组最大长度
typedef struct{ //定义线性表结构体
int data[MAXSIZE] //线性表存储元素的数组
int length;//记录线性表的长度
}*SqList;
11.3线性表的操作
顺序线 性表初始化
bool Init_SqList(SqList *l){
L→data=(int *)maloc(MAX_SIZE*sizeof(int))
if(!L→data)return false;
else{
L→length=0;
return true;
}
}
顺序线性表的插入
int ListInsert(SqList *L,int i,int e){
int k;
if(L→length==MAXSIZE) //顺序线性表已经满
return 0;
if(i<1||i>L→length+1)//当i比第一位置小或者比最后一位置后一位置还要大时//
return 0;
if(i<=L→length){//若插入数据位置不在表尾
for(k=L→length-1;k>=i-1;k--)//将要插入位置后的元素向后移一位
L→data[k+1]=L→data[k];
}
L→data[i-1]=e; //将新元素插入
L→length++;
return 1;
}