数据结构
绪论
程序=数据结构+算法
数据结构是介于数学,计算机硬件和计算机软件三者之间的一门核心课程
勤于思考,多做练习,多上机,善于寻求帮助,不怕困难不放弃
具体问题抽象为数据模型(分析问题,提取操作对象,找出操作对象之间的关系,用数学语言描
述),设计算法,编程、调试、运行
增删改查
表,树,图
数据:能输入计算机且能被计算机处理的各种符号的集合。信息的载体,是对客观事物符号化的表示,能够被计算机识别、存储和加工。包括整数、实数、文字、图像、图形、声音
数据元素:是数据的基本单位,在计算机程序中通常作为一个整体进行考虑和处理,也简称为元素,或称为记录,结点或顶点
数据项:构成数据元素的不可分割的最小单位
数据>数据元素>数据项
数据对象:是性质相同的数据元素的集合,是数据的一个子集
数据结构包括:逻辑结构,(物理结构,存储结构)数据的运算和实现
线性结构:有且只有一个开始和一个终端结点,并且所有的节点都最多只有一个直接前驱和一个直接后继:线性表,栈,队列,串
非线性结构:一对多,多对一。一个节点可能有多个直接前驱和直接后继,例如:树,图
集合,线性,树,图
顺序存储结构:用一组连续的存储单元一次存储数据元素,数据元素之间的逻辑关系由元素的存储位置来表示
链接存储结构:用一组任意的存储单元存储数据元素,数据元素之间的逻辑关系用指针来表示
索引存储结构:在存储节点信息的同时,还建立附加的索引表
散列存储结构:根据节点的关键字直接计算出该节点的存储地址
int char float double
数据类型是一组性质相同的值的集合以及定义于这个值集合上的一组操作的集合
抽象数据类型形式定义:(D,S,P)D:是数据对象S:是D上的关系集P:是对D的基本操作集
算法:对特定问题求解方法和步骤的一种描述
流程图:传统流程图,NS流程图
一个问题可以有多种算法
算法特性:有穷性,确定性,可行性,输入,输出
算法设计的要求:正确性,可读性,健壮性,高效性
算法分析:时间效率,空间效率
为了便于比较不同算法的时间效率,我们仅比较数量级(渐进表示法)
T(n)=O(f(n)) 时间复杂度
例 :T(n)=O(n的三次方)
一般情况下,不必计算所有操作的执行次数,而只考虑算法中基本操作执行的次数
常数项去掉,只保留最高次项的数量级(忽略所有低次幂项和最高次幂系数)
1.找出语句频度最大的那条语句作为基本语句
2.计算基本语句的频度得到问题规模n的某个函数f(n)
3.取其数量级用符号“O”表示
x=0;y=0;
for(int k=0;k<n;k++)
x++;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
y++;
时间渐进复杂度:T(n)=O(n的平方)
空间复杂度:算法所需存储空间的度量
S(n)=O(f(n))
抽象数据类型=数据的逻辑结构+抽象运算
字母表:数据元素是字母,元素间关系是线性
线性表:典型线性结构
线性表中数据元素的类型可以为简单类型,也可以为复杂类型
顺序存储结构和链式存储结构
顺序存储结构,逻辑结构上相邻,物理结构上也相邻
顺序表:地址连续,依次存放,随机存取,类型相同
线性表长可变
数组长度不可动态定义
顺序表的查找算法分析:因为查找算法的基本操作为:将记录的关键字同给定值进行比较
基本操作:L.elem[i]==e
平均查找长度ASL(Average Search Length)(n+1)/2
为确定记录在表中的位置,需要与给定值进行比较的关键字的个数的期望值叫做查找算法的平均查找长度
顺序表插入:
顺序表放在最后的位置,最简单,直接放置就好
顺序表插入位置在中间,把插入位置后面的元素依次往后搬,把那个位置空出来,在插入
顺序表插入位置在最前面,如上
算法思想:
1.判断插入位置i是否合法
2.判断顺序表的存储空间是否已满,若已满返回error
3.将n至第i位的元素依次向后移动一个位置,空出第i个位置
4.将要插入的新元素e放入第i个元素
5.表长加1,插入成功返回ok
算法时间主要耗费在移动元素的操作上
若插入在尾节点之后,则根本无需移动(特别快)
若插入在首节点之前,则表中元素全部后移(特别慢)
若要考虑各种位置插入(共n+1种可能)的平均移动次数,该如何计算?n/2
顺序表删除:
删除位置在最后:直接删除就行
删除位置在中间:删除位置后的元素依次往前搬
删除位置在最前面:如上
算法思想:
1.判断删除位置i是否合法(合法值为1<i<n)
2.将欲删除的元素保留在e中
3.将第i+1至第n位的元素依次向前移动一个位置
4.表长减1,删除成功返回OK
算法时间主要耗费在移动元素的操作上
若删除尾节点,则根本无需移动(特别快)
若删除首节点,则表中n-1个元素全部前移(特别慢)
若要考虑在各种位置删除(共n种可能)的平均移动次数,给如何计算?n-1/2
顺序表的特点:
1.利用数据元素的存储位置表示线性表中相邻数据元素之间的前后关系,即线性表的逻辑结构与存储结构一致
2.在访问线性表时,可以快速计算出任意一个数据元素的存储位置。因为可以粗略的认为,访问每个元素所花时间相等
这种存储方法是随机存储法
查找,插入,删除算法的平均时间复杂度为O(n)
空间复杂度为O(1)(没有占用辅助空间)
优点:存储密度大(节点本身所占存储量/节点存储所占存储量)
可以随机存取表中任意元素
缺点:在插入,删除某一元素时,需要移动大量元素
浪费存储空间
属于静态存储形式,数据元素的个数不能自由扩充
链式存储:
逻辑结构和物理结构不一定一致
一个节点有两部分,数据域和指针域
单链表:节点只有一个指针域的链表,称为单链表或线性链表
双链表:节点有两个指针域的链表,称为双链表
循环链表:首尾相连的链表称为循环链表
头指针:是指向链表中第一个节点的指针
首元结点:是指链表中存储第一个数据元素的节点
头节点:是在链表的首元结点之前附设的一个节点
链表分为:
1.不带头结点
2.带头结点
在链表中设置头结点有什么好处?
1.便于首元结点的处理
首元结点的地址保存在头结点的指针域中,所以在链表的第一个位置上的操作和其他位置一直,无须进行特殊处理
2.便于空表和非空表的统一处理
无论链表是否为空,头指针都是指向头结点的非空指针,因为空表和非空表的处理也就统一了
头结点的数据域内装的是什么?
头结点的数据域可以为空,不计入链表长度中
链表特点
1.节点在存储器中的位置是任意的,即逻辑上相邻的数据元素在物理上不一定相邻。
2.访问时只能通过头指针进入链表,并通过每个节点的指针域依次向后顺序扫描其余节点,所以寻找第一个节点和最后一个节点所花费的时间不等
循环链表:前驱节点,数据域,后继节点
单链表的销毁:链表销毁后不存在
从头指针开始,依次释放所有节点
清空链表:链表仍存在,单链表中无元素,变成空链表
依次释放所有节点,并将头结点指针设置为空
求链表的表长:从首元结点开始,依次计数所有节点
单链表的基本操作:
单链表的销毁
清空单链表
求单链表的的表长
判断链表是否为空
取值:从链表的头指针出发,顺着链域next逐个节点往下搜索,直至搜索到第i个节点为止。因此,链表不是随机存取结构
查找:
1.按值查找:
从第一个节点起,依次和相比较
如果找到一个其值与e相等的数据元素,则返回其在链表中的位置或地址
如果查遍整个链表都没有找到其值和e相等的元素,则返回0或NULL
插入:在第i个节点前插入值为e的新节点
首先找到ai-1的存储位置p
生成一个数据域为e的新节点s
插入新节点,新节点的指针域指向节点ai,节点ai-1的指针域指向新节点
删除:删除第i个节点
首先找到ai-1的存储位置p,保存要删除的ai的值
令p->next指向ai+1
单链表的查找,插入,删除算法时间效率分析
查找:O(n)
插入和删除:O(1)
单链表优缺点:
单链表的建立:
头插法:1.从一个空表,重复读入数据
2.生成新节点,将读入数据存放到新节点的数据域中
3.从最后一个节点开始,依次将各节点插入到链表的前端
后插法:1.从一个空表L开始,将新节点逐个插入到链表的尾部,为指针r指向链表的尾结点
2.初始时,r同L均指向头结点,每读入一个数据元素则申请一个新节点,将新节点插入到尾节点后,r指向新结点
循环链表:是一种首尾相连的链表
优点:从表中任意结点出发均可找到表中其他结点
双向链表:左指针域,数据域,右指针域
让头结点的前驱指针指向链表的最后一个节点
让最后一个节点的后继指针指向头结点
链式存储结构的优点:
节点空间可以动态申请和释放
数据元素的逻辑次序靠节点的指针来指示,插入和删除时不需要移动数据元素
链式存储结构的缺点:
存储密度小,每个节点的指针域需要额外占用存储空间,当每个节点的数据域所占字节不多时,指针域所占存储空间的比重显得很大
链式存储结构式非随机存取结构,对任意节点的操作都要从头指针依指针链查找到给节点,这增加了算法的复杂度
有序表的合并:
已知线性表La和Lb中的数据元素按值非递减有序排列,现要求将La和Lb归并为一个新的线性表Lc,且Lc中的数据元素仍按值非递减有序排列
创建一个空表Lc
依次从La或Lb中摘取元素值较小的节点插入到Lc表的最后,直至其中一个表变空为止
继续讲La或Lb其中一个表的剩余节点插入到Lc表的最后
栈和队列:
栈和队列是两种常见的,重要的数据结构
栈和队列是限定插入和删除只能在表的端点进行的线性表
栈–后进先出
队列–先进先出
栈和队列是线性表的子集(是插入和删除位置受限的线性表)
栈(stack)是一个特殊的线性表,是限定仅在一端进行插入和删除操作的线性表,LIFO
表尾称为栈顶,表头称为栈底
入栈:插入元素到栈顶 PUSH
出栈:删除最后一个元素的操作 POP
入栈顺序a,b,c那么出栈顺序有哪些?
abc
cba
bac
acb
栈的相关概念
1.定义:限定只能在表的一端进行插入和删除运算的线性表
2.逻辑结构:与同线性表相同,仍为一对一关系
3.存储结构:用顺序栈或链栈均可,但以顺序栈更常见
4.运算规则:只能在栈顶运算,且访问节点时依照后进先出(LIFO)的规则
5.实现方式:关键是编写入栈和出栈函数,具体实现依顺序栈或链栈的不同而不同
队列是一种先进先出(FIFO)的线性表,在表的一端插入,在另一端删除
队列的相关概念:
1.定义:只能在表的一端进行插入运算,在表的另一端进行删除运算的线性表
2.逻辑结构:与同线性表相同,仍为一对一关系
3.存储结构:顺序队或链队,以循环顺序队列更常见
4.运算规则:只能在队首和队尾运算,且访问节点时依照先进先出(FIFO)的原则
5.实现方式:关键是掌握入队和出队操作,具体实现依顺序队或链队的不同而不同
栈的应用:进制转换,符号对称检验,表达式求值等等
算符优先算法:
表达式的组成:
操作数:常数,变量
运算符:算符运算符,关系运算符和逻辑运算符
界限符:左右括号和表达式结束符
例:#3*(7-2)#
为了实现表达式求值,需要设置两个栈:
一个是算符栈OPTR,用于寄存运算符
另一个称为操作数栈OPND,用于寄存运算数和运算结果
求值的处理过程是自左至右扫描表达式的每一个字符
当扫描到的是运算数,则将其压入栈OPND,
当扫描到的是运算符时:
若这个运算符比OPTR栈顶运算符的优先级高,则入栈OPTR,继续向后处理
若这个运算符比OPTR栈顶运算符的优先级低,则从OPND栈中弹出两个运算数,从栈OPTR中弹出栈运算符进行运算,并将运算结果压入栈OPND
继续处理当前字符,直到遇到结束符位置
栈的表示和操作的实现:
存储方式:同一般线性表的顺序存储结构完全相同,利用一组地址连续的存储单元依次存放自栈底到栈顶的数据元素,栈底一般在低地址端
附设top指针,指示栈顶元素在顺序栈中的位置(但是,为了方便操作,通常top指示真正的栈顶元素之上的下标地址)
另设base指针,指示栈底元素在顺序栈中的位置
空栈:base==top是栈空标志
栈中元素个数=top-base
链栈的表示:
链栈是运算受限的单链表,只能在链表头部进行操作
链表的头指针就是栈顶
不需要头结点
基本不存在栈满的情况
空栈相当于头结点指向空
插入和删除仅在栈顶出执行
递归的定义
若一个对象部分地包含他自己,或用他自己给自己定义,则称这个对象是递归的
若一个过程直接地或间接地调用自己,则称这个过程是递归的过程
分治法:对于一个比较复杂的问题,能够分解成几个相对简单的且揭发相同或类似的子问题来求解
函数调用过程:
调用前:
将实参,返回地址等传递个被调用函数
为被调用函数的局部变量分配存储区
将控制转移到被调用函数的入口
调用后:
保存被调用函数的计算结果
释放被调用函数的数据区
依照被调用函数保存的返回地址将控制转移到调用函数
队列的表示和操作的实现
队列(Queue)是仅在表尾进行插入操作,在表头进行删除操作的线性表
表尾称为队尾,表头称为对头
先进先出(FIFO)
插入元素称为入队,删除元素称为出队
队列的存储结构为链队或顺序队(常见循环顺序队)
若front=0
rear=MAXQSIZE时
再入队–真溢出
若front不等于0
rear=MAXQSIZE时
再入队–假溢出
解决假上溢的方法:
将堆空间设想成一个循环的表,即分配给队列的m个存储单元可以循环使用,当rear为maxqsize时,若向量开始端空着,又可从头试用空着的空间。当front为maxqsize时,也是一样
若用户无法估计所用队列的长度,则宜采用链队列
串,数组和广义表
栈和队列是操作受限的线性表
串中元素中只能是字符,属于内容受限的线性表
子串:一个串中任意个连续字符组成的子序列称为该串的子串
例如,“abcde”的子串有:“”,“a”,“ab”,“abc”,“abcd”,“abcde”等
真子串是指不包括自身的所有子串
子串:串中任意个连续字符组成的子序列称为该串的子串
主串:包括子串相应的称为主串
字符位置:字符在序列中的序号为该字符在串中的位置
子串位置:子串第一个字符在主串中的位置
空格串:由一个或多个空格组成的串,与空串不同
串相等:当且仅当两个串的长度相等并且各个对应位置上的字符都相同时,这两个串才是相等的
串的链式存储结构:
优点:操作方便
缺点:存储密度较低
串的模式匹配算法
确定主串中所包含子串第一次出现的位置
BF算法
KMP算法
主串指针i不必回溯
数组:按一定格式排列起来的
具有相同类型的数据元素的集合
稀疏矩阵可以用三元组法来表示(行坐标,列坐标,数值)
三元组顺序表的优点:非零元在表中按行序有序存储,因此便于进行依行顺序处理的矩阵运算
三元组顺序表的缺点:不能随机存取,若按行号存取某一行中的非零元,则需从头开始进行查找
十字链表:
优点:他能灵活的插入因运算而产生的新的非零元素,删除因运算而产生的新的零元素,实现矩阵的各种运算
在十字链表中,矩阵的每一个非零元素用一个节点表示,该节点除了(row,col,value)以外,还要有两个域:
right:用于连接同一行中的下一个非零元素
down:用于连接同一列中的下一个非零元素
广义表:
表头:若LS非空,则其第一个元素a1就是表头,注:表头可以使原子,也可以是子表
表尾:出表头之外的其他元素组成的表。注:表尾不是最后一个元素,而是一个子表
A=() 空表,长度为0
B=(())长度为1,表头,表尾均是()
C=(a,(b,c))长度为2,由原子a和子表(b,c)构成
表头为a,表尾为((b,c))
D=(x,y,z)长度为3,每一项都是原子
表头为x,表尾为(y,z)
E=(C,D)长度为2,每一项都是子表
表头为C,表尾为(D)
F=(a,F)长度为2,第一项为原子,第二项为它本身
表头为a,表尾为(F)
F(a,(a,(a,…)))
广义表中的数据元素有相对次序,一个直接前驱和一个直接后继
广义表的长度定义为最外层所包含的元素个数
如:C=(a,(b,c))是长度为2的广义表
广义表的深度定义为该广义表展开后所含括号的重数
A=(b,c)的深度为1,B=(A,d)的深度为2,C=(f,B,h)的深度为3
原子的深度为0,空表的深度为1
广义表可以看成是线性表的推广,线性表时广义表的特例
广义表结构相当灵活,在某种前提下,他可以兼容线性表,数组,数和有向图等各种常用的数据结构
当二维数组的每行作为子表处理时,二维数组即为一个广义表
另外,树和有向图也可以用广义表来表示
由于广义表不仅集中了线性表,数组,数和有向图等常见数据结构的特点,而且可有效地利用存储空间,因此在计算机的许多引用领域都有成功使用广义表的实例
树型结构:
树是n个节点的有限集
树的其他表示方式:嵌套集合,广义表,凹入表示
根节点:非空树种无前驱节点
节点的度:节点拥有的子树数
树的度:树内各节点的度的最大值
度=0,叶子,终端节点
度=/0,分支节点,非终端节点,根节点以外的分支节点称为内部节点
节点的子树的根称为该节点的孩子,该节点称为孩子的双亲
节点的祖先:从根到该节点所经分支上的所有节点
节点的子孙:从某节点为根的子树中任一节点
树的深度:树中节点的最大层次
有序树:树中节点的各子树从左至右有次序
无序树:树中节点的各子树无次序
森林:是m(>=0)棵互不相交的树的集合
把根节点删除树就变成了森林
一颗树可以看成是一个特殊的森林
给森林中的各子树加上一个双亲节点,森林就变成了树
树一定是森林,森林不一定是森林
二叉树的结构最简单,规律性最强
二叉树是n(n>=0)个节点的有限集,他或者是空集(n=0),或者由一个根节点及两棵互不相交的分别称为这个跟的左子树和右子树的二叉树组成
特点:
每个节点最多有两孩子
子树有左右之分,其次序不能颠倒
二叉树可以输空集合,根可以有空的左子树或空的右子树
二叉树不是树的特殊情况,他们是两个概念
二叉树节点的子树要区分左子树和右子树,及时只有一棵子树也要进行区分,说明他是左子树还是右子树
树当节点只有一个孩子时,就无序区分他是左还是右的次序,因此二者是不同的,这是二叉树和树的最主要的差别
二叉树的5种基本形态:
空二叉树
根和空的左右子树
根和左子树
根和右子树
根和左右子树
性质1:在二叉树的第i层上至多有2的i-1次方个节点
性质2:深度为k的二叉树至多有2的k次方-1个节点
性质3:对任何一颗二叉树T,如果其叶子数为n0,度为2的节点数为n2,则n0=n2+1
性质4:具有n个节点的完全二叉树的深度为log2n的底+1
二叉树的顺序存储:
适用于满二叉树和完全二叉树
二叉树的链式存储:
节点:左孩子,数值,右孩子
在n个节点的二叉链表中,有n+1个空指针域
三叉链表
节点:左孩子,数值,双亲结点,右孩子
遍历二叉树:顺着某一条搜索路径巡防二叉树中节点,使得每个节点均被访问依次,而且仅被访问一次
遍历目的:得到树中所有节点的一个线性排列
先序遍历:根节点,左子树,右子树
中序遍历:左子树,根节点,右子树
后序遍历:左子树,右子树,根节点
已知二叉树的先序和中序序列,构造出相应的二叉树
先序:ABCDEFGHIJ
中序:CDBFEAIHGJ
已知一棵二叉树的
先序序列:BDCEAFHG
后序序列:DECBHGFA,请画出这棵二叉树
线索二叉树:
利用二叉链表的空指针域:
如果某个节点的左孩子为空,则将空的左孩子指针域改为指向其前驱;如果某节点的右孩子为空,则将空的右孩子指针域改为指向其后继,这种改变指向的指正称为线索,加上线索的二叉树称为线索二叉树
ltag=0 lchild指向该节点的左孩子
ltag=1 lchild指向该节点的前驱
rtag=0 rchild指向该节点的右孩子
rtag=1 rchild指向该节点的后继
双亲表示法
数据域:存放节点本身信息
双亲域:指示本节点的双亲节点在数组中的位置
0 | R(数据域) | -1(双亲域) |
---|---|---|
1 | A | 0 |
2 | B | 0 |
3 | C | 0 |
4 | D | 1 |
5 | E | 1 |
6 | F | 3 |
7 | G | 6 |
8 | H | 6 |
9 | I | 6 |
孩子链表
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3X5fp4l3-1583892663490)(C:\Users\MY\Desktop\56672F90BF711716E6A6FE5967EA6CAF.png)]
孩子兄弟表示法
实现:用二叉链表做树的存储结构,链表中的每个节点的两个指针域分别指向其第一个孩子节点和下一个兄弟节点
树和二叉树的转换
将树转换成二叉树
加线:在兄弟之间加一连线
抹线:对每个节点,除了其左孩子外,去除其与其余孩子之间的关系
旋转:以树的根节点为轴心,将整树顺时针转45°
口诀:兄弟相连留长子
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PqfE21qd-1583892663491)(C:\Users\MY\Desktop\723F699EB5D8EECFF51D9268CAD122B6.png)]
将二叉树转换成树
加线:若p节点时双亲节点的左孩子,则将p的右孩子,右孩子的右孩子…沿分支找到的所有右孩子,都与p的双亲用线连起来
抹线:抹掉原二叉树中双亲的右孩子之间的连线
调整:将节点按层次排列,形成树结构
口诀:左孩右右连双亲,去掉原来右孩线
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w9AiHvfm-1583892663492)(C:\Users\MY\Desktop\39684DD1C64A60C707AB378AB71C9DD9.png)]
森林转换成二叉树
将各棵别转换成二叉树
将每棵树的根节点用线相连
以第一棵树根节点为二叉树的根,在以根节点为轴心,顺时针旋转,构成二叉树型结构
口诀:树变二叉根相连
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fLgGp9bm-1583892663493)(C:\Users\MY\Desktop\9CF836731274DEF1CFCAFB75D6E67024.png)]
二叉树转换成森林
抹线:将二叉树中根节点与其右孩子连线,及沿右分支搜索到的所有右孩子间连线全部抹掉,使之变成孤立的二叉树
还原:将孤立的而出书还原成树
口诀:去掉全部右孩线,孤立二叉再还原
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AOHPMRMI-1583892663493)(C:\Users\MY\Desktop\A44F7F37DCF6FC019F8D4339534F4DD9.png)]
树的遍历
先根遍历:
后跟遍历:
层次遍历:
将森林看做有三部分构成:
1.森林中第一棵树的根节点
2.森林中第一棵树的子树森林
3.森林中其他树构成的森林
森林的遍历:
先序遍历
中序遍历
后序遍历
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SVOxQ4u2-1583892663494)(C:\Users\MY\Desktop\C5425990149015EB9BCBDE847937B0B7.png)]
哈夫曼树:
路径:从树中一个节点到另一个节点之间构成这两个节点间的路径
节点的路径长度:两节点间路径上的分支数
权:将树中节点赋给一个有着某种含义的数值,则这个数值成为该节点的权
节点的带权路径长度:从跟根节点到该节点之间的路径长度与该节点的权的乘积
哈夫曼树:最优树(带权路径长度最短的树)
构造森林全是根
选用两小造新树
删除两小添新人
哈夫曼编码:
若将编码设计为长度不等的二进制编码,即让待传字符串中出现次数较多的字符采用尽可能短的编码,则转换的二进制字符串便可能减少
关键:要设计长度不等的编码,则必须使任一字符的编码都不是另一字符的编码的前缀
哈夫曼编码设计
统计字符集中每个字符在电文中出现的平均概率
利用哈夫曼树的特点:权越大的叶子离根越近;将每个字符的概率作为权值,构造哈夫曼树。则概率越大的节点,路径越短。
在哈夫曼树的每个分支上标0或1:节点的左分支标0,右分支标1。把从根到每个叶子的路径上的标号连接起来,作为该叶子代表的字符的编码
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WAySjgtT-1583892663494)(C:\Users\MY\Desktop\6AFBE2B5F5356999E47A8E3EFB522934.png)]
为什么哈夫曼编码能够保证是前缀编码?
因为没有一片树叶是另外一片树叶的祖先,所以每个叶节点的编码就不可能是其他叶节点编码的前缀
为什么哈夫曼编码能够保证字符编码总长最短?
因为哈夫曼树的带权路径长度最短,故字符编码的总长最短
图:G(V,E)
V:顶点的有穷非空集合
E:边的有穷集合
无向图:每条边都是无方向的
有向图:每条边都是有方向的
完全图:任意两个点都有一条边相连
稀疏图:有很少边或弧的图
稠密图:有较多边或弧的图
网:边/弧带权的图
领接:有边/弧相连的两个顶点之间的关系
关联:边/弧与顶点之间的关系
顶点的度:与该顶点相关联的边的数目
在有向图中,顶点的度等于该节点的入度和出度之和
存储结构:
图没有顺序存储结构,但可以借助二维数组来表示元素间的关系:数组表示法
链式存储结构:多重链表:领接表,领接多重表,十字链表
领接矩阵表示法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l0biMgV8-1583892663495)(C:\Users\MY\Desktop\0FE823D7606C986460BFB87C37D24465.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-26dJzuOk-1583892663496)(C:\Users\MY\Desktop\AD5505C5D63ABD841E7DBADEF7A38FED.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UynX4a1E-1583892663496)(C:\Users\MY\Desktop\AD5505C5D63ABD841E7DBADEF7A38FED.png)]
领接矩阵有什么不好?
不便于增加和删除顶点
浪费空间-存稀疏图
浪费时间-统计稀疏图中一共有多少条边
领接表表示法(链式)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Eor8eCMX-1583892663497)(D:\523856995\FileRecv\MobileFile\DACC0340B05B7F4E8A23B35120351CA2.png)]
领接表特点:
方便找任一顶点的所有领接点
节约稀疏图的空间
方便计算任一顶点的度?
对无向图:是的
对有向图:只能计算出度;需要构造逆领接表来方便计算入度
不方便检查任意一对顶点间是否存在边
领接矩阵与领接表表示法的关系
1,联系:领接表中每个链表对应于领接矩阵中的一行,链表中节点个数等于一行中非零元素的个数
2,区别:对于任一确定的无向图,领接矩阵是唯一的,但领接表不唯一(前插法,后插法)
领接矩阵的空间复杂度为n的平方,领接表的空间复杂度为r+e
3,用途:玲姐矩阵多用于稠密图;而领接表多用于稀疏图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ioBkknlU-1583892663498)(D:\523856995\FileRecv\MobileFile\4E5C6189D093B1B2C35248FCF462EA57.png)]
十字链表
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3Aif8UJN-1583892663501)(D:\523856995\FileRecv\MobileFile\D88B595B83F71622D89CFD54C8656949.png)]
领接多重表
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GcHJjaKK-1583892663502)(D:\523856995\FileRecv\MobileFile\D88B595B83F71622D89CFD54C8656949.png)]
图的遍历:
深度优先遍历-DFS
时间复杂度:领接矩阵O(n的平方),O(领接表n+e)
广度优先搜索-BFS
时间复杂度:领接矩阵O(n的平方),O(领接表n+e)
比较:空间复杂度相同都是O(n)
时间复杂度只与存储结构有关,而与搜索路径无关
生成树:所有顶点均由边连接起来,但不存在回路的图
一个图可以有很多棵不同的生成树
所有生成树具有以下共同特点
1.生成树的顶点个数与图的顶点个数相同
2.生成树是图的极小连通子图,去掉一条边则非连通
最小生成树:给定义个无向网络,在该网的所有生成树中,使得各边权值之和最小的那颗生成树称为该网的最小生成树,也叫最小代价生成树
普里姆算法 :选择点:适合稠密图:时间复杂度n的平方
克鲁斯卡尔算法:选择边:适合稀疏图:时间复杂度:eloge
最短路径:
Dijkstra算法:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3QlkVHjM-1583892663502)(D:\523856995\FileRecv\MobileFile\D587B250F6FA917F230667DE92AFA301.png)]
有向无环图:无环的有向图
查找:
如何评价查找算法?
查找算法的评价指标:
关键字的平均比较次数,也称为平均查找长度
复杂度为n的平方,领接表的空间复杂度为r+e
3,用途:玲姐矩阵多用于稠密图;而领接表多用于稀疏图
[外链图片转存中…(img-ioBkknlU-1583892663498)]
十字链表
[外链图片转存中…(img-3Aif8UJN-1583892663501)]
领接多重表
[外链图片转存中…(img-GcHJjaKK-1583892663502)]
图的遍历:
深度优先遍历-DFS
时间复杂度:领接矩阵O(n的平方),O(领接表n+e)
广度优先搜索-BFS
时间复杂度:领接矩阵O(n的平方),O(领接表n+e)
比较:空间复杂度相同都是O(n)
时间复杂度只与存储结构有关,而与搜索路径无关
生成树:所有顶点均由边连接起来,但不存在回路的图
一个图可以有很多棵不同的生成树
所有生成树具有以下共同特点
1.生成树的顶点个数与图的顶点个数相同
2.生成树是图的极小连通子图,去掉一条边则非连通
最小生成树:给定义个无向网络,在该网的所有生成树中,使得各边权值之和最小的那颗生成树称为该网的最小生成树,也叫最小代价生成树
普里姆算法 :选择点:适合稠密图:时间复杂度n的平方
克鲁斯卡尔算法:选择边:适合稀疏图:时间复杂度:eloge
最短路径:
Dijkstra算法:
[外链图片转存中…(img-3QlkVHjM-1583892663502)]
有向无环图:无环的有向图
查找:
如何评价查找算法?
查找算法的评价指标:
关键字的平均比较次数,也称为平均查找长度