大话数据结构第3-7章(读书笔记)

大话数据结构第3-7章(读书笔记)

第三章 线性结构

Tips: 数组的长度总大于线性表的长度

3.1线性表的顺序存储

存取读入数据时,都是O(1),插入删除数据时,都是O(n)

结构优点缺点
线性表顺序存储无需增加额外的存储空间,快速存储插入删除需要移动大量元素,难以确定存储容量,造成存储空间的“碎片”

3.2线性表的链式存储(单链表)

链式存储分为 单链表,静态链表,循环,双向链表,这里着重讲单链表

1.含义
存储数据元素信息的域成为数据域
存储直接后继位置的域称为指针域
结点的含义:指针域和数据域组成数据元素的存储映像
每个结点只包含一个指针域,称之为单链表

2.特点
一般,最左边为头指针,最右边最后一个结点的指针指向空。
一般会在单链表的第一个结点之前设置一个节点,称为头结点,可以不存储任何信息,头结点的指针是指向第一个结点的指针
如果线性表为空表,那么头结点的指针域为空

异同头指针头结点
1指向第一个结点的指针,具有标识作用,且头指针不可为空,是必要因素一般此数据域无意义,不是必要要素

3.3单链表的读取

读取算法思路:
1.声明一个指针p,指向链表第一个结点,初始化j从1开始;
2.当j<i时遍历链表,让p的指针向后移动,不断指向下一个节点,j累加1
3.若到链表末尾p为空的时候,则说明第i个结点不存在
4.否则查找成功,返回结点p的数据。

算法思路

3.4单链表的插入与删除

  • 插入s: s-next = p-next; p-next = s (p-next-next = p-next,用s取代p-next)
  • 删除q:q=p-next; p-next = q-next (p-next= p-next-next,用q取代p-next)

插入算法思路:
1.声明一指针P指向链表头结点,初始化j从1开始;
2.当j<i时遍历链表,让p的指针向后移动,不断指向下一个节点,j累加1
3.若到链表末尾p为空的时候,则说明第i个结点不存在

4.否则查找成功,在系统中生成一个空结点s
5.将数据元素e 赋值给 s-data
6.单链表的插入标准语句s-next = p-next; p-next = s
7.返回成功

算法思路

删除算法思路:
1.声明一指针P指向链表头结点,初始化j从1开始;
2.当j<i时遍历链表,让p的指针向后移动,不断指向下一个节点,j累加1
3.若到链表末尾p为空的时候,则说明第i个结点不存在

4.否则查找成功,将与删除的结点p-next 赋值给 q
5.单链表的删除标准语句q=p-next; p-next = q-next
6.将q结点中的数据赋值给e,作为返回
7.释放q结点
8.返回成功

算法思路

插入与删除的时间复杂度:O(n)

3.5单链表的整表创建与删除

创建单链表的整表是一种动态结构,该过程是一个动态生成链表的过程
过程:空表–建立各元素结点–逐个插入链表

创建算法思路:(头插法) 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
算法思路

3.6顺序存储vs单链表

  • 顺序存储:查找O(1),插入O(n),需要预分配空间
  • eg注册信息
  • 单链表: 查找O(n),插入O(1),不需要预分配空间
  • eg游戏装备

当线性表中的元素个数变化比较大,适合单链表。
当线性表中事先知道该表的长度,比如一年12月,一星期7天等,适合顺序存储

第四章 栈与队列

  • 栈:后进先出,只在表尾进行插入删除的线性表
  • 队列:先进先出,只在一端进行插入,另一端进行删除的线性表

4.1 栈stack

将允许插入和删除的一端成为栈顶(top),另一端称为栈底(bottom);插入与删除都必须在栈顶进行,这也限制了插删的位置,栈底是固定的。

栈又称作 后进先出的线性表(Last in first out ),简称LIFO结构
生活中的例子:网页的后退键,word的撤销键

栈的插入与删除
栈的插入(push)为 进栈,压栈,入栈,删除(pop)称为出栈或弹栈

4.1.1 栈的顺序存储

空栈的top为-1,栈中有两个元素top=1,栈中有5个元素top=4
进栈出栈的时间复杂度为O(1),但需要事先确定一个固定的长度,存在内存空间浪费的问题,但是优势就是存取时定位方便

4.1.2 栈的链式存储

进栈出栈的时间复杂度为O(1),但要求每个元素有指针域,增加内存开销,不需要提前确定长度

4.1.3 栈的应用–递归

** 经典的递归例子: 斐波那契数列(Fibonacci)**

  • 可以使用迭代和递归进行实现
  • 迭代:循环结构
  • 递归:选择结构,结构清晰,更简洁,减少内存
 斐波那契数列(Fibonacci)
中缀表达式和后缀表达式转化
方法:从左到右遍历中缀表达式,若是数字就输出,若是符号,则判断其余栈顶符号的优先级,紧挨着符号右侧项进行输出
中缀:9+(3-1)*3+10/2
后缀:9 3 1- 3*+ 10 2/+

4.2 队列queue

4.2.1队列的定义

允许插入的一端称为队尾,允许删除的一端称为队头,a1是队头,an是队尾
队列又称作 先进先出的线性表(Firsr in first out ),简称FIFO结构
生活中的例子:排队;电脑卡机,然后又运行过来,会把之前的操作按顺序进行一遍

4.2.2 队列的顺序存储

插入为O(1),删除为O(n)

4.2.3 队列的链式存储

循环队列(顺序):可以确定队列长度最大值的情况下使用
链队列(链式): 无法预估队列的长度
时间复杂度都为O(1)

第五章 串String–P213

定义:由零个或多个字符组成的有限序列,又称字符串。
一般操作有:查找位置,得到位置,替换子串

编码
ASCII 编码:7位二进制表示一个字符,总128字符
ASCII扩展:8位二进制表示一个字符,总256字符
Unicode编码:16位二进制表示一个字符,总6.5万个字符,前256同上

5.1 串的顺序存储

5.2 串的算法

5.2.1 朴素模式匹配
5.2.2 KMP模式匹配

(适用于模式与主串之间存在许多部分匹配的情况)

第六章 树Tree–P255

定义:
树是n(n>=0)个结点的有限集,n=0为空树

特点

  • 1.有且仅有一个特定的称为根(Root)的结点
  • 2.n>1时,其余结点可分为m(m>0)个互不相交的有限集T1,T2…,Tm
  • 3.每一个集合本身又是一棵树,并且成为根的子树(Subtree)

6.1结点概念

6.1.1 结点分类

树的结点:包括 一个数据元素 及 若干指向其子树的分支
结点的度:结点拥有的子树数称为结点的度(De-gree)
叶节点:度为0的结点称为叶节点(Leaf)或终端结点
分支结点:度不为0的结点称为分支结点或非终端结点
内部节点:除根节点之外的分支结点
树的度:树内各节点的度的最大值

6.2.2结点间关系

结点的孩子child:结点的子树,该结点称为孩子的父节点parent
兄弟sibling:同一个父节点下面的孩子之间的互称
结点的祖先:从根到该结点所经分支上所有节点,有1个或多个

6.2 树的存储结构

深度(Depth):树的层数称为树的高度深度
森林(Forest):是m棵互不相交的树的集合。对树中每个结点而言,其子树的集合称为森林

异同线性结构树结构
01第一个数据元素:无前驱;最后一个:无后继;中间元素:前驱+后继根结点:无双亲;叶结点:无孩子,可以多个;中间结点:一个双亲多个孩子

三种方式:双亲表示法,孩子表示法,孩子兄弟表示法

6.2.1双亲表示法
  • 结构:[data][parent] data储存数据信息,parent存储数组下标
  • 时间复杂度为O(1) ;parent为-1表示根节点;该例子的数的度为3

Alt text

Alt text

6.2.2孩子表示法
  • 孩子链表的孩子结点–结构:[child][next]
    child为数据域,用于保存表头数据中的下标;
    next为指针域,保存指向下一结点的指针

  • 表头数据的表头结点–结构:[data][firstchild]
    data为数据域,存储某结点的数据信息
    firstchild 为头指针域,存储头指针,即左子树

Alt text

6.2.3孩子兄弟表示法
  • 结构:[data][firstchild][rightsib]
    data为数据域,存储某结点的数据信息
    firstchild 为指针域,存储头指针,即左子树
    right-sib 为指针域,存储该节点的右兄弟地址

Alt text

6.3二叉树

特点:
1.每个结点最多两颗子树,度一定小于等于2,可以为0,1,2
2.左子树和右子树是有顺序的,次序不可颠倒
3.即使某结点只有一颗子树,也要区分是左还是右
4.五种形态:

1.空二叉树
2.只有一个根结点
3.根结点只有左子树
4.根结点只有右子树
5.根结点有左、右子树

6.3.1特殊二叉树
  • 斜树
    只有左子树 or 只有右子树 的二叉树
  • 满二叉树
    每个分支结点都有左右子树,那么称为满二叉树
  • 完全二叉树
    相当于满二叉树的一部分,数值一定要是连续的

完全二叉树特点:

1.叶子结点只能出现在最下两层
2.最下层的叶子一定集中在左部连续位置
3.倒数第二层,若有叶子结点,一定都在右部连续位置
4.结点度数为1,那么该结点只有左,没有右
5.同样结点树的二叉树,完全二叉树的深度最小


以下完全二叉树,数值连续
Alt text

以下不是完全二叉树,数值不连续
Alt text

—2018-11-06 P291

6.3.2 二叉树的性质

推荐网址:Latex公式汇总
性质1
在二叉树的第i层上至多有 2 i − 1 2^{i-1} 2i1个结点(i>=1)
eg: 第一层1 第二层2 第三层4 第四层8
性质2
深度为K的二叉树至多有 2 k − 1 2^k -1 2k1 个结点
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

6.3.3 二叉树的存储结构

顺序存储会占用大量内存,适用性不强,所以着重讲链式存储

  • 结构[lchild][data][rchild]
    data 数据域
    child指针域

6.4 二叉树的遍历

含义:
二叉树的遍历(traversing binary tree) 是指从根结点出发,按照某种**【次序】依次【访问】**二叉树中的所有结点,使得每个结点被访问一次,且仅被访问一次。

【技巧】
已知前序和中序,可以唯一确定一颗二叉树
已知后序和中序,可以唯一确定一颗二叉树
已知前序和后序,不一定可以确定二叉树
前序遍历:
根节点在前
(1)先遍历根结点左侧的所有左子树,然后左侧所有右子树(次序是不同的根结点从下到上)
(2)右侧所有左子树,右侧所有右子树(次序是同结点依次向下只有右子树,那么从上到下)
(3)顺序:根节点-左子树-右子树

中序遍历:
根节点在中
(1)先遍历最下层的左侧的第一个左子树
(2)顺序:左子树-根结点-右子树

后序遍历:
根节点在后
(1)先遍历最下层的左侧第一个左子树,然后同级别的右子树(如果没有左子树,则从右子树开始)
(2)顺序:左子树-右子树-根结点

主要讲四种:前序,中序,后序,层序


四种的前提:若二叉树为空,则空操作返回

前序遍历

  • 先访问根结点,然后前序遍历左子树,再前序遍历右子树
    ABDGHCEIF
    Alt text

中序遍历

  • 从根结点开始,中序遍历根节点的左子树,然后访问根节点,中序遍历右子树
    GDHBAEICF
    Alt text

后序遍历

  • 从左到右先叶子后结点的方法访问左右子树,最后访问根结点
    GHDBIEFCA
    Alt text

6.5线索二叉树

6.5二叉树的应用–赫夫曼编码

(数据压缩)

第七章 图Graph–P364

定义:
图是由顶点的有穷非空集合和顶点之间边的集合组成,表示为G(V,E),其中G表示一个图,V是图G中顶点的集合,E是图G中边的集合

7.1深度优先与广度优先

深度优先类似于树的前序遍历,广度优先类似于树的层序遍历
两者的时间复杂度是一样的
深度优先适合 目标更明确,以找到目标为目的
广度优先适合 在不断扩大便利范围时找到相对最优解

7.1.1Prim算法
7.1.2Kruskal算法

7.2最短路径

7.2.1 Dijkstra算法
7.2.2 Floyd算法
7.2.3 拓扑结构
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值