Tips: 数组的长度总大于线性表的长度
存取读入数据时,都是O(1),插入删除数据时,都是O(n)
结构 | 优点 | 缺点 |
---|---|---|
线性表顺序存储 | 无需增加额外的存储空间,快速存储 | 插入删除需要移动大量元素,难以确定存储容量,造成存储空间的“碎片” |
链式存储分为 单链表,静态链表,循环,双向链表,这里着重讲单链表
1.含义
存储数据元素信息的域成为数据域
存储直接后继位置的域称为指针域
结点的含义:指针域和数据域组成数据元素的存储映像
每个结点只包含一个指针域,称之为单链表
2.特点
一般,最左边为头指针,最右边最后一个结点的指针指向空。
一般会在单链表的第一个结点之前设置一个节点,称为头结点,可以不存储任何信息,头结点的指针是指向第一个结点的指针
如果线性表为空表,那么头结点的指针域为空
异同 | 头指针 | 头结点 |
---|---|---|
1 | 指向第一个结点的指针,具有标识作用,且头指针不可为空,是必要因素 | 一般此数据域无意义,不是必要要素 |
读取算法思路:
1.声明一个指针p,指向链表第一个结点,初始化j从1开始;
2.当j 3.若到链表末尾p为空的时候,则说明第i个结点不存在
4.否则查找成功,返回结点p的数据。
算法思路
插入算法思路:
1.声明一指针P指向链表头结点,初始化j从1开始;
2.当j 3.若到链表末尾p为空的时候,则说明第i个结点不存在4.否则查找成功,在系统中生成一个空结点s
5.将数据元素e 赋值给 s-data
6.单链表的插入标准语句s-next = p-next; p-next = s
7.返回成功
算法思路
删除算法思路:
1.声明一指针P指向链表头结点,初始化j从1开始;
2.当j 3.若到链表末尾p为空的时候,则说明第i个结点不存在4.否则查找成功,将与删除的结点p-next 赋值给 q
5.单链表的删除标准语句q=p-next; p-next = q-next
6.将q结点中的数据赋值给e,作为返回
7.释放q结点
8.返回成功
算法思路
插入与删除的时间复杂度:O(n)
创建单链表的整表是一种动态结构,该过程是一个动态生成链表的过程
过程:空表–建立各元素结点–逐个插入链表
创建算法思路:(头插法) or 尾插法
1.声明一指针p和计数器变量i
2.初始化一个空链表L
3.让L的头结点的指针指向NULL,也就是建立一个带头结点的单链表
4.循环:
- 生成一新节点赋值给p
- 随机生成一数字赋值给p的数据域 p-data
- 将p插入到头结点与前一新节点之间
算法思路
删除算法思路:
1.声明一指针p和指针q
2.将第一个结点赋值给p
3.循环:
- 将下一个结点赋值给q
- 释放p
- 将q 赋值给 p
算法思路
当线性表中的元素个数变化比较大,适合单链表。
当线性表中事先知道该表的长度,比如一年12月,一星期7天等,适合顺序存储
将允许插入和删除的一端成为栈顶(top),另一端称为栈底(bottom);插入与删除都必须在栈顶进行,这也限制了插删的位置,栈底是固定的。
栈又称作 后进先出的线性表(Last in first out ),简称LIFO结构
生活中的例子:网页的后退键,word的撤销键
栈的插入与删除
栈的插入(push)为 进栈,压栈,入栈,删除(pop)称为出栈或弹栈
空栈的top为-1,栈中有两个元素top=1,栈中有5个元素top=4
进栈出栈的时间复杂度为O(1),但需要事先确定一个固定的长度,存在内存空间浪费的问题,但是优势就是存取时定位方便
进栈出栈的时间复杂度为O(1),但要求每个元素有指针域,增加内存开销,不需要提前确定长度
** 经典的递归例子: 斐波那契数列(Fibonacci)**
- 可以使用迭代和递归进行实现
斐波那契数列(Fibonacci)
中缀表达式和后缀表达式转化
方法:从左到右遍历中缀表达式,若是数字就输出,若是符号,则判断其余栈顶符号的优先级,紧挨着符号右侧项进行输出
中缀:9+(3-1)*3+10/2
后缀:9 3 1- 3*+ 10 2/+
允许插入的一端称为队尾,允许删除的一端称为队头,a1是队头,an是队尾
队列又称作 先进先出的线性表(Firsr in first out ),简称FIFO结构
生活中的例子:排队;电脑卡机,然后又运行过来,会把之前的操作按顺序进行一遍
插入为O(1),删除为O(n)
循环队列(顺序):可以确定队列长度最大值的情况下使用
链队列(链式): 无法预估队列的长度
时间复杂度都为O(1)
定义:由零个或多个字符组成的有限序列,又称字符串。
一般操作有:查找位置,得到位置,替换子串
编码:
ASCII 编码:7位二进制表示一个字符,总128字符
ASCII扩展:8位二进制表示一个字符,总256字符
Unicode编码:16位二进制表示一个字符,总6.5万个字符,前256同上
堆
(适用于模式与主串之间存在许多部分匹配的情况)
定义:
树是n(n>=0)个结点的有限集,n=0为空树
特点
树的结点:包括 一个数据元素 及 若干指向其子树的分支
结点的度:结点拥有的子树数称为结点的度(De-gree)
叶节点:度为0的结点称为叶节点(Leaf)或终端结点
分支结点:度不为0的结点称为分支结点或非终端结点
内部节点:除根节点之外的分支结点
树的度:树内各节点的度的最大值
结点的孩子child:结点的子树,该结点称为孩子的父节点parent
兄弟sibling:同一个父节点下面的孩子之间的互称
结点的祖先:从根到该结点所经分支上所有节点,有1个或多个
深度(Depth):树的层数称为树的高度深度
森林(Forest):是m棵互不相交的树的集合。对树中每个结点而言,其子树的集合称为森林
异同 | 线性结构 | 树结构 |
---|---|---|
01 | 第一个数据元素:无前驱;最后一个:无后继;中间元素:前驱+后继 | 根结点:无双亲;叶结点:无孩子,可以多个;中间结点:一个双亲多个孩子 |
三种方式:双亲表示法,孩子表示法,孩子兄弟表示法
特点:
1.每个结点最多两颗子树,度一定小于等于2,可以为0,1,2
2.左子树和右子树是有顺序的,次序不可颠倒
3.即使某结点只有一颗子树,也要区分是左还是右
4.五种形态:1.空二叉树
2.只有一个根结点
3.根结点只有左子树
4.根结点只有右子树
5.根结点有左、右子树
完全二叉树特点:
1.叶子结点只能出现在最下两层
2.最下层的叶子一定集中在左部连续位置
3.倒数第二层,若有叶子结点,一定都在右部连续位置
4.结点度数为1,那么该结点只有左,没有右
5.同样结点树的二叉树,完全二叉树的深度最小
—2018-11-06 P291
推荐网址:Latex公式汇总
性质1
在二叉树的第i层上至多有 2 i − 1 2^{i-1} 2i−1个结点(i>=1)
eg: 第一层1 第二层2 第三层4 第四层8
性质2
深度为K的二叉树至多有 2 k − 1 2^k -1 2k−1 个结点
eg: 一层1 二层1+2 三层1+2+4 四层1+2+4+8
性质3(难理解,记住)
对任何一颗二叉树T,如果其终端叶子结点数为n0,度为2的结点数为n2,那么 n 0 = x 2 + 1 n_0 =x_2 + 1 n0=x2+1
设n1是度数为1的结点数,那么数的总结点数为: n = n 0 + x 1 + x 2 n = n_0 + x_1 + x_2 n=n0+x1+x2
性质4
具有n个结点的完全二叉树的深度为:
∣ log 2 n + 1 ∣ |\log_2 n + 1| ∣log2n+1∣
性质5
对于完全二叉树来说,分枝结点中,左子树通常为该双亲节点*2,右子树在此基础加1
顺序存储会占用大量内存,适用性不强,所以着重讲链式存储
含义:
二叉树的遍历(traversing binary tree) 是指从根结点出发,按照某种**【次序】依次【访问】**二叉树中的所有结点,使得每个结点被访问一次,且仅被访问一次。
【技巧】
已知前序和中序,可以唯一确定一颗二叉树
已知后序和中序,可以唯一确定一颗二叉树
已知前序和后序,不一定可以确定二叉树
前序遍历:
根节点在前
(1)先遍历根结点左侧的所有左子树,然后左侧所有右子树(次序是不同的根结点从下到上)
(2)右侧所有左子树,右侧所有右子树(次序是同结点依次向下只有右子树,那么从上到下)
(3)顺序:根节点-左子树-右子树中序遍历:
根节点在中
(1)先遍历最下层的左侧的第一个左子树
(2)顺序:左子树-根结点-右子树后序遍历:
根节点在后
(1)先遍历最下层的左侧第一个左子树,然后同级别的右子树(如果没有左子树,则从右子树开始)
(2)顺序:左子树-右子树-根结点主要讲四种:前序,中序,后序,层序
四种的前提:若二叉树为空,则空操作返回
前序遍历
中序遍历
后序遍历
(数据压缩)
定义:
图是由顶点的有穷非空集合和顶点之间边的集合组成,表示为G(V,E),其中G表示一个图,V是图G中顶点的集合,E是图G中边的集合
深度优先类似于树的前序遍历,广度优先类似于树的层序遍历
两者的时间复杂度是一样的
深度优先适合 目标更明确,以找到目标为目的
广度优先适合 在不断扩大便利范围时找到相对最优解