无结构阶段:在简单数据上作复杂运算
结构化阶段:数据结构+算法=程序
面向对象阶段:(对象+行为)=程序
计算机求解问题:
问题——抽象出问题的模型——求模型的解
问题:数值问题。非数值问题
数值问题:数学方程
非数值问题:数据结构
数据结构研究对象:非数值计算问题中的计算机的操作对象以及它们之间的关系和操作的学科
数据:一切 能输入到计算机中并能被计算机程序识别和处理的符号集合。
数值数据:整数、实数,布尔,字符等;
非数值数据:图形、图象、声音、文字等
数据元素:数据的基本单位
数据项:构成数据元素的不可分割的最小单位。
数据对象:具有相同性质的数据元素的集合
结点:数据元素在计算机内的位串表示
域:就是数据项在计算机内的表示
数据结构:数据元素之间的相互关系
数据结构分为:逻辑结构、存储结构
数据的逻辑结构:数据元素之间的抽象关系,数据元素之间逻辑关系的整体;是从具体问题中抽象出来的数据模型。
数据的存储结构:是数据及其逻辑结构在计算机中的表示。实质是内存分配。
数据结构从逻辑上分为四类:
1.集合:属于同一个集合
2.数据线性结构:数据元素之间存在一对一的线性关系
3.树形结构:数据元素之间存在一对多的层次关系。
4.图结构:数据元素之间存在多对多的任意关系。
两种基本的存储结构:
1.顺序存储结构:连续的存储单元依次存储数据元素,逻辑关系由存储位置表示。
2.链接存储结构:一组任意的存储单元存储数据元素,数据元素之间的逻辑关系用指针来表示。
抽象数据类型(ADT)
抽象数据类型(Abstract Data Type)
定义:一个数学模型和在该模型上定义的操作集合的总称
1.ADT是程序设计语言中数据类型概念的进一步推广和进一步抽象。
算法:是对特定问题求解步骤的一种描述,是指令的有限序列。
算法的五大特性:
1.输入:一个算法有0个或多个输入
2.输出:一个算法有一个或多个输出。
3.有穷性:一个算法必须总是在执行有穷步之后结束,且每一步都在有穷时间内完成:
4.确定性:算法中每一条指令必须有确切的含义,对于相同的输入只能得到相同的输出。
5.可行性:算法描述的操作可以通过已经通过已经实施的基本操作执行有限次来实现。
算法分析——时间复杂度分析
算法的执行时间=每条语句执行时间之和
执行次数×执行一次的时间
执行一次的时间(单位时间)=指令系统、编译的代码质量
算法的执行时间→每条语句的执行次数之和→基本的执行次数
算法执行时间,是基本(操作)语句重复执行的次数,它是问题规模的一个函数,我们把这个函数的渐近阶称为该算法的时间复杂度。
问题规模:输入量的多少。
基本语句:是执行次数与整个算法的执行次数成正比的操作指令。
算法分析:——大O符号
定义 若存在两个正的常数c和n0,对于任意n≥n0,都有T(n)≦c×f(n),则称T(n)=O(f(n))
定理:若A(n)是一个m次的多项式,则A(n)=O(n的m次方)
定理说明渐近阶只由最高次幂决定
说明:在计算算法时间复杂度时,可以忽略所有低次幂(低阶)项和高次幂(最高阶)项的系数。
时间复杂性的运算法则
①加法法则:
②乘法规则:
小结:数据接哦故与算法的五个方面
数据的逻辑结构:线性结构:线性表 栈 队列
非线性结构:树形结构 图形结构
数据的存储结构:顺序存储 链式存储 散列存储(哈希存储)索引存储
数据的操作(算法):检索、排序、插入、删除、修改等
线性表
线性表由一组数据元素构成,由零个或多个数据元素组成的有限序列。
非空线性表的结构特征:
(1)且只有一个根结点a1,它无前驱;
(2)有且只有一个终端结点an,它无后继;
(3)除根结点与终端结点外,其他所有结点有且只有一个前驱,也有且只有一个后继,结点个数n称为线性表的长度,当n=0时,称为空表。
线性表的顺序存储结构具有以下两个基本特点:
线性表由一组数据元素构成,指的是用一段地址连续的存储单元依次存储线性表的数据元素,元素之间的相对位置是线性的。
在复杂线性表中,由若干项数据元素组成的数据元素称为记录,而由多个记录构成的线性表又称为文件。
线性表的顺序存储结构具有以下两个基本特点:
1.线性表中所有元素的所占的存储空间是连续的;
2.线性表中各数据元素在存储空间中是按逻辑顺序依次存放的。
ai的存储地址为:adr(ai)=adr(a1)+(i-1)k,,adr(a1)为第一个元素的地址,k代表每个元素占的字节数。
顺序表的运算:插入、删除。
线性表的链式存储结构的特点:是用一组任意的存储单元存储线性表的数据元素,这组存储单元可以存在内存中未被占用的任意位置。
也就是说,链式存储结构的线性表由一个(可以使零)或者多个结点(Node)组成。每个节点内部又分为数据域和指针域(链)。数据域存储了数据元素的信息。指针域存储了当前结点指向的直接后继的指针地址。
因为每个结点只包含一个指针域,所以叫做单链表。顾名思义,当然还有双链表。
单链表:单链表的上一个结点指针指向下一个结点,最后一个结点的指针域为null。
双链表:双链表拥有一前一后两个指针域,从两个不同的方向把链表连接起来,如此一来,从两个不同的方向形成了两条链,因此成为双链表。
循环链表: 循环链表是数据结构中链表的一种形式。相对于单向链表,将单向链表的尾结点的指针域指向该单向链表的头结点,就构成了循环链表。
链式存储结构中,除了要存储数据元素信息外,还要存储它的后继元素的存储地址(指针)。也就是说除了存储其本身的信息外,还需存储一个指示其直接后继的存储位置的信息。我们把存储数据元素信息的域称为数据域,把存储直接后继位置的域称为指针域。
栈和队列
栈 (Stack)是一种后进先出(last in first off,LIFO)的数据结构,而队列(Queue)则是一种先进先出 (fisrt in first out,FIFO)的结构。
栈:
栈是限定仅在表尾进行插入和删除操作的线性表。 把插入和删除的一端称为栈顶(TOP),另一端称为栈底(BOTTOM),不包含任何元素的栈称为空栈。栈又称为后进先出(Last in first out)的线性表,简称LIFO结构。 由于栈也是线性表,因此线性表的存储结构对栈也使用,通常有顺序栈和链栈两种存储结构,这两种存储结构的不同,即使得实现栈的基本运算的算法也有所不同。
(1)顺序存储结构
其实栈的顺序存储还是挺方便的,因为他只准栈顶进出元素,所以不存在线性表插入和删除时需要移动元素的问题。不过它有一个很大的缺陷,就是必须事先确定数组存储空间大小,空间不够用了,就需要编程手段来扩展数组的容量,非常麻烦。
(2)链式存储结构
如果栈的使用过程中元素变化不可预测,有时很小,有时非常大,那么最好是用链栈【存储空间不固定可伸缩】。
队列:
队列的定义:
队列(queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。
队列是一种先进先出(first in first out)的线性表,简称FIFO。允许插入的一端称为队尾(rear),允许删除的一端称为队头(Front)。
队列是一种运算受限的线性表,它的运算限制与栈不同,是两头都有限制,插入只能在表的一端进行(只进不出),而删除只能在表的另一端进行(只出不进)。
队列的存储结构:
队列也是线性表,所以有两种存储方式,顺序存储和链式存储。
(1)顺序存储结构(顺序队列)
缺点,存储空间不够用的时候需要开发人员通过编程手段来扩展数组容量。
衍生循环队列:头尾相接的顺序存储结构成为循环队列。
(2)链式存储结构(链队)
队列的链式存储结构,其实也就是线性表的单链表,只不过它只能尾进头出而已,我们把它简称为链队列。
(3)循环队列
串
串的逻辑结构和线性表相似,区别仅为串的数据对象约束为字符集
串的基本操作和线性表有很大差别,线性表的基本操作中大多以的“单个元素”作为操作对象;而串的基本操作中通常以“串的整体”作为操作对象。
串的表示:
1、定长顺序存储表示:
超过预定义长度的串值则被舍弃,称为“截断”。
对串长的表示方法:在下标为0的数组分量存放串的实际长度;在串值后面加一个结束标记字符“\0”。
2、堆分配存储表示:
仍以一组地址连续的存储单元存放,但存储空间是在程序执行过程中动态分配的。
C中动态分配函数:malloc(),free()。
3、串的块链存储表示:
存在结点大小问题:每个结点可以存放1个字符,也可存放多个,则最后一个结点不一定被占满,通常补上“#”或其他非串值字符。
为便于进行串的操作,除头指针外还可附设一个尾指针,并给出当前串的长度。
一般情况下,只需要从头向尾顺序扫描,则对串值不必建立双向链表。设尾指针为了方便联结操作,联结时需处理第一个串尾的无效字符。
存储密度=串值所占存储位/实际分配存储位。
串的模式匹配算法:
BF:
KMP:
数组和广义表
数据结构中最基本的一个结构就是线性结构,而线性结构又分为连续存储结构和离散存储结构。所谓的连续存储结构其实就是数组。
数组的存储在计算机内存中是一片连续的区域。而且数组中每一项所占内存的大小是一定的。
① 数组中各元素具有统一的类型;
② 数组元素的下标一般具有固定的上界和下界,即数组一旦被定义,它的维数和维界就不再改变。
③数组的基本操作比较简单,除了结构的初始化和销毁之外,只有存取元素和修改元素值的操作。
数组的顺序存储表示和实现:
事先约定按某种次序将数组元素排成一列序列,然后将这个线性序列存入存储器中。
行优先顺序:存储时先按行从小到大的顺序存储,在每一行中按列号从小到大存储。
列优先顺序:存储时先按列从小到大的顺序存储,在每一列中按行号从小到大存储。
无论规定行优先或列优先,只要知道以下三要素便可随时求出任一元素的地址
① 始结点的存放地址(即基地址)
② 维数和每维的上、下界;
③ 每个数组元素所占用的单元数
一维数组:
loc(ai)=loc(a1)+(i-1)*c
m*n的二维数组(共有m行,每行有n列)
loc(aij)=loc(a11)+[(i-1)*n+j-1]*c
三维数组R[p][m][n]:
loc(i,j,k)= LOC(0,0,0) +(i*m*n +j*n+k) *c
矩阵的压缩储存:
首先是特殊矩阵的压缩。对于有规律的特殊矩阵,如对角矩阵、下(上)三角矩阵,对角矩阵。可以根据规律将矩阵存在一维数组中,建立起原始下标与压缩后矩阵下标的对应关系就好。
对没有规律的稀疏矩阵,只存储稀疏矩阵的非0元。需要三元组表存储(行、列、元素值)。根据三元组表的不同表示方式,得到稀疏矩阵不同的压缩存储方法。
①三元组顺序表 以行序为主序排列。 就是用个数组存起来,行号小的放前面。 讲了下这种结构下转置的操作,关键讲了下如何在转置后以行为主排序。又讲了个快速转置,就是存储了原矩阵每一列首元素的位置和每一列元素个数,这样就不用在之后排序了,直接放在对的位置就好了。
②行逻辑链接的顺序表,就是把每行第一个非0位置存了起来,为了方便抽取任意一行。讲了两个稀疏矩阵相乘的例子,说来说去就是为了去掉0与其他元素相乘这样冗余的计算需要行起始位置,具体没看,太繁琐。没什么新技术。
③十字链表 在两个稀疏矩阵相加时,非零元素数量变化可能很大,不宜采用顺序存储结构。 这种结构每个非零元有5个域(行、列、值、该行下一元素指针、该列下一元素指针) 用两个一维数组存储每一行和每一列的头结点。
广义表: