数据结构笔记

一级目录

二级目录

三级目录

C++补充知识

键盘输入字符串
string s;
getline(cin,s);

string s; getline(cin,s);//获取一行数据 cout<<s;

如果函数的传入参数类似*&p,则传入的时候可以传入一个对应类型的指针

动态分配需要导入stdlib

字符处理函数需要导入cstring

STL

sort函数

导入#include<algorithm>后可以直接使用sort函数对数组排序
sort(起始地址,结束地址,less<int>());即可排序,降序是greater<int>()

vector

vector构造,导入#inlcude<vector>后使用vector<类型> 变量名;
vector v;//定义一个空vector
vector v2(4);//定义一个4个大小的vector,初始为0
vector v3(4,6);//定义一个4个大小的vector,初始为6
vector v{1,2,3,4,5};//定义一个vector,数字为1,2,3,4,5
for(auto x:v3) cout<<x;//遍历vector

可以使用[]获取元素或使用v.at(index)获取元素

v.push_back()追加内容

v.resize(元素个数)可以重置大小并将全部元素置0

v.erase(v.begin());//删除第一个元素
v.erase(–v.end());//删除最后一个元素

获取第一个元素
v.front();
v[0];
v.begin();
获取最后一个元素
v.back();
v.size()-1];//size是获取大小
v.end();

stack

构造栈
stack s;

入栈用s.push(元素);
出栈用s.pop();(没有返回值)
取栈顶元素是s.top();
查看元素个数用s.size();

queue

构造队列
queue q;

插入元素q.push(元素);
删除队首元素q.pop();

取队首q.front();

队列长度q.size();

绪论章节

绪论

数据:所有能够输入到计算机中,且能被计算机处理的符号的集合。

数据结构主要讨论结构化数据

数据元素:数据(集合)中的一个“个体”,它是数据的基本单位**(具体数值)**

数据项:描述数据元素的,是数据最小单位**(数据的标题)**

数据对象:具有相同性质的若干个数据元素的集合**(整数数据对象是所有整数的集合)**

数据结构=数据对象+数据元素之间的关系

主要讨论相邻关系或邻接关系

数据结构包含逻辑结构、存储结构、数据运算

二元组表示法:B=(D+R),B是数据结构,D是数据元素,R是D上二元关系的集合

邮箱序偶<x,y>,x和y分别是第一元素和第二元素,x和y分别是对方的前驱元素和后继元素

无前驱的是开始元素,无后继的是终端元素

(x,y)是无向序偶

四种逻辑结构:
集合(除了“属于一个集合,数据元素之间没有其他关系”)
线性结构(开始和终端元素都是唯一的,其他元素仅有一个前驱和后继元素)
线性表、栈、队列、串、数组
树形结构(开始元素唯一,终端元素不唯一,每个元素仅有一个前驱元素)
树、二叉树
图形结构(多对多)

数据逻辑结构在计算机中的存储表示称为数据的存储结构,也称为物理结构

四种基本的存储结构:顺序存储结构、链式存储结构、索引存储结构、哈希存储结构

数据运算分为运算定义和运算实现,关系如下图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UHyAjPqZ-1619420467811)(D:%5Cimage%5CtyporaImage%5Cimage-20200217091030663.png)]

同一种逻辑结构可以对应多种存储结构

同样的运算,在不同的存储结构中,其实现过程是不同的

数据类型是一个值的定义和定义在此集合上的一组操作的总称**(int是整数数据类型)**

数据类型就是已经实现了的数据结构

抽象数据类型(ADT(DSP))=数据结构+抽象运算**(例如C++编写一个复数类)**
D是数据对象,S是D上的关系集,P是对D的基本操作集

算法及其描述

通常把基于存储结构的运算实现的步骤或过程称为算法

算法的五个特性:有穷性、确定性、可行性、输入、输出

算法设计的目标:正确性、可使用性、可读性、健壮性、高效性

算法分析

算法分析的目的是分析算法的时空效率以便改进算法性能

CPU时间分析:时间性能分析

内存空间分析:空间性能分析

算法由控制结构(顺序、分支、循环)和原操作(算术运算、逻辑运算等)构成

分析方式:事前(统计执行时间)和事后(认为算法的执行时间是问题规模n的函数)

时间复杂度
没有循环:O(1)
一重循环:O(n)
平方阶
立方阶
对数阶:O(log2n)
指数阶:O(2n)

时间复杂度比较关系如下图,一般认为越小则算法的时间性能越好
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zKWwB5BR-1619420467813)(D:%5Cimage%5CtyporaImage%5Cimage-20200217092648968.png)]

分析时间复杂度时考虑基本操作x其运算次数

简化分析的办法:直接看循环最深层的语句的频度

递归求数组最大值的空间复杂度为O(log2n)

线性表

基本概念

线性表是一个具有相同特性的数据元素的有限序列(抽象数据结构)
相同特性:所有元素属于同一数据类型
有限:数据元素个数是有限的
序列:数据元素由逻辑序号唯一确定,一个线性表中可以有相同值的元素

线性表的长度:所含元素个数n,若n=0,则是空表
a1是表头元素,an是表尾元素

九个基本运算:
初始化
销毁
判断是否为空表
求长度
输出线性表(不为空时顺序显示各节点的值域)
求特定位置的元素
定位查找(按值查找位置)
插入元素
删除元素

线性表的存储结构
顺序存储结构
链式存储结构
单链表
双链表
循环链表

顺序存储结构

概念:按逻辑次序依次存储到一片连续的存储空间中(直接映射)

双链表

插入节点
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-o8tikvJD-1619420467815)(D:%5Cimage%5CtyporaImage%5Cimage-20200224104946694.png)]

删除节点
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8mUEk3kM-1619420467817)(D:%5Cimage%5CtyporaImage%5Cimage-20200224105026406.png)]

二路归并使用顺序表时,时间和空间复杂度均为O(m+n),其中m和n是链表各自的长度

易错题

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9y5pIbIH-1619420467818)(D:%5Cimage%5CtyporaImage%5Cimage-20200413104909844.png)]
注意不是循环链表,只能走到末尾过去

栈和队列

顺序栈

栈空条件:top=-1
栈满条件:top=MaxSize-1
进栈操作:top++;将e放在top处
退栈操作:从top处取出元素e;top–

有n个数顺序(依次)进栈,出栈序列有Cn种,Cn=[1/(n+1)](2n)!/[(n!)(n!)]

共用栈
栈顶往中间生长,栈底固定在两端
根据左栈顶+1是否等于右栈顶来判断是否满

顺序队

队空条件:front=rear
队满条件:rear=MaxSize-1
元素进队:rear++;datalrear]=e
元素出队:front++;e=datalfront]

循环环形队列
队空条件:front=rear
队满条件:(rear+1)%MaxSize=front
进队操作:rear=(rear+1)%MaxSize;将e放在rear处
出队操作:front=(front+1)%MaxSize;取出front处元素e**(有时候从0计数的话记得修正maxsize要加一,例如存储在A[0…m]的循环队列则入队操作为rear=(rear+)%(m+1))**
未掉头时队尾指针一般在队头指针右侧

错题:循环队列通常用指针来实现队列的头尾相接(错误)

循环队列进队时rear指针向前,出队时front指针向前(相对于圆环向前是指数字变大)

已知front、rear,求队中元素个数count:
count=(rear-front+MaxSize)%MaxSize
已知front、count,求rear:
rear=(front+count)%MaxSize
已知rear、count,求front:
front=(rear-count+MaxSize)%MaxSize

双端队列
允许在一端进行插入和删除,但在另一端只允许插入的双端队列叫做输出受限的双端队列
允许在一端进行插入和删除,但在另一端只允许删除的双端队列叫做输入受限的双端队列

链队

队空条件:front=rear=NULL
队满条件:不考虑
进队操作:将包含e的节点插入到单链表表尾
出队操作:删除单链表首数据节点,修改front指针指向下一个

删除元素,可能既要修改头指针也要修改尾指针,因为可能只有一个元素
考虑三种情况:多个元素,单个元素,空表

易错题

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tW0Ch9OT-1619420467820)(D:%5Cimage%5CtyporaImage%5Cimage-20200413105636411.png)]

串的基本概念和存储结构

串(string)是由零个或多个字符组成的有限序列
串属于线性表
串的逻辑表示:ai(1≤i≤n)代表一个字符**(串从1开始计数)**
串相等:长度相等并且对应位置的字符相同
字串是任意个连续的字符组成的子序列(非空,非原串)
substr(原始串,开始位置,长度)
若串为a1…an则字串的个数是1+2+…+n
串拷贝函数
void strcpy(char* s,char* t)//t拷贝到s
{
while((*s++ = *t++) != ‘\0’)
}

顺序串

char data[]和int length

非紧缩格式:每个单元存一个字符,存储密度小
紧缩格式:每个单元存多个字符,存储密度大

链串

*char data和struct snode next

链串中每个节点所存储的字符个数称为节点大小

串的模式匹配

在串s中找一个与t相等的子串,s是目标串,t是模式串,串查找定位也称为模式匹配

朴素算法

BF暴力算法,采用穷举法,依次从目标串的各个字符开始进行尝试匹配直到匹配成功
模式串长度为m,目标串长度为n
最好情况的时间复杂度是O(m),最坏和平均复杂度都是O(nxm)
若模式串的长度≈目标串,则BF更节省时间,不需要计算next数组,时间复杂度为O[(n-m+1)n]

KMP算法

next数组第一个0,第二个1,第三个开始看前面的字串前后匹配的最大长度k,记录为k+1
匹配了部分然后遇到不同时,向后移动的位数是已经匹配的长度-最后一个匹配字符对应的next数组值(这个是0开头版本的next数组,匹配的前后缀字符数+1得到next值;教材的next和nextval均是-1开头的版本,直接等于匹配的长度)

kmp算法的时间复杂度:O(m+n)

递归

直接递归:直接调用自己
间接递归:间接调用自己,例如两个函数互相调用,一般间接递归总是可以转换成直接递归

如果一个递归函数中递归调用语句是最后一条执行语句,则称这种递归调用为尾递归

尾递归算法:可以用循环语句转换为等价的非递归算法
其他递归算法;可以通过栈来转换为等价的非递归算法

递归模型由递归出口和递归体组成
前者确定递归结束情况
后者确定大小问题的求解情况

在系统实现递归调用时需利用递归工作记录保存实际参数的值
在传值参数情形,需为对应形式参数分配空间,以存放实际参数的副本
在引用参数情形,需保存实际参数的地址,在被调用程序中可直接操纵实际参数

利用递归求解数组最小值
f(A,i)=A[0]当i为0时
f(A,i)=MIN(f(A,i-1),A[i])

递归(recursion):递归常被用来描述以自相似方法重复事物的过程,在数学和计算机科学中,指的是在函数定义中使用函数自身的方法(A调用A)

迭代(iteration):重复反馈过程的活动,每一次迭代的结果会作为下一次迭代的初始值(A重复调用B)

递归是一个树结构,从字面可以其理解为重复“递推”和“回归”的过程,当“递推”到达底部时就会开始“回归”,其过程相当于树的深度优先遍历

迭代是一个环结构,从初始状态开始,每次迭代都遍历这个环,并更新状态,多次迭代直到到达结束状态

理论上递归和迭代时间复杂度方面是一样的,但实际应用中(函数调用和函数调用堆栈的开销)递归比迭代效率要低

易错题

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7XEJ8DhS-1619420467821)(D:%5Cimage%5CtyporaImage%5Cimage-20200413102616715.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ySOFhDDx-1619420467822)(D:%5Cimage%5CtyporaImage%5C0YZW57N0%60ZJ$%5BQ%60I_U%7D2%25G.jpg)]
对于这个题,在几个章节的作业中都出现了,但是依然有错的情况。现在我把解答详细步骤发给大家。其中的令k=log2n的依据是当n=1时,T(n)=1,这是递归的出口,到此反弹回去,即结束继续深度调用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WqUgK6SC-1619420467823)(D:%5Cimage%5CtyporaImage%5CHFDNBQATJ5TGSFSDSPIZ1YQ.png)]
这一题读起来有些拗口。但是实际是在问函数调用时参数传递的是什么?因为是”值”传递,当然传递的是“值”而不是地址

数组和稀疏矩阵

数组

特性
元素数目固定
数据元素具有相同数据类型
每个元素有唯一下标
数据是随机存储结构,可以随机存取任意元素

特殊矩阵:对称矩阵、上下三角矩阵、对角矩阵(均为方阵)

对称矩阵的压缩存储
若ai,j=aj,i那么a数组就是对称矩阵

压缩存储对称矩阵:只存储下三角元素,利用一个一维数组Bk存放
B数组共有n(n+1)/2个元素
当i≥j时,k=i(i+1)/2+j,若i<j,则将i和j在公式中交换即可

存储上三角矩阵(对角线以下为常量)则B数组中有i(2n-i+1)/2

稀疏矩阵

含有大量零元素的无规则矩阵

系数矩阵的压缩存储方法是只存储非零元素

稀疏矩阵中每一个非零元素用一个三元组(i,j,ai,j)所有非零元素构成三元组线性表

定义三元组的结构体TupNode
int r行号
int c列号
ElemType d元素值

定义三元顺序表TSMatrix(注意计算三元组存储所需字节数时,不仅计算3*非零元素个数*字节数,还要加上3*字节数*,用于保存行数、列数和非零元素个数)
int rows行数值
int cols列数值
int nums非零元素个事
TupNode data[MaxSize]

三元组矩阵的赋值,首先检测对应位置是否为0,若不为0则可以直接修改数值,否则要将这一位以及之后的元素全部后移一位,空出这一位才能赋值

十字链表

  1. 对于稀疏矩阵,每个非零元素都创建一个节点,假设原矩阵为m行n列

  2. 同一行的节点都构成一个循环单链表,各行的循环单链表表头组成一个数组为hr[0]-hr[i],hr[i]指针指向i行的首节点

  3. 同一列的节点都构成一个循环单链表,各列的循环单链表表头组成一个数组为hd[0]-hd[j],hd[j]指针指向j列的首节点

  4. 这样就有m+n个循环单链表,头结点个数也一样,实际上可以合并,h[i]同时含有行指针和列指针,这样数目减少为MAX(m,n)

  5. 再将所有头节点h[i]连起来构成一个带头节点的循环单链表,这样需要一个总头节点hm,总头节点中存放稀疏矩阵的行数和列数等信息

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-88tVerNr-1619420467825)(D:%5Cimage%5CtyporaImage%5Cimage-20200328133109509.png)]
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-67CJeXda-1619420467826)(D:%5Cimage%5CtyporaImage%5Cimage-20200328133118901.png)]
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mIs57Lvb-1619420467826)(D:%5Cimage%5CtyporaImage%5Cimage-20200328133132795.png)]
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DVDDBCb6-1619420467827)(D:%5Cimage%5CtyporaImage%5Cimage-20200328133148716.png)]

广义表

  • 广义表的定义

    广义表是线性表的推广,是有限个元素的序列,采用括号表示法GL=(a1,a2,…,an)

    1. n=0是为空表
    2. ai为第i个元素,如果ai为原子类型,则成为GL广义表的原子
    3. 若ai为广义表,则称ai为广义表GL的子表

    几个重要概念

    • 广义表的长度为最外层包含的元素个数
    • 深度定义为所含括弧的重数,其中原子的深度为0,空表的深度为1
    • a1为GL的表头,其余部分为表位,一个广义表的表尾始终是一个广义表,空表无表头表尾

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TrYYtDjT-1619420467828)(D:%5Cimage%5CtyporaImage%5Cimage-20200413164034770.png)]

  • 广义表的几个常用操作(取表头、取表尾、求表长)

    • 求长度,因为同一层次的节点是通过link域连接起来的,所以直接视作求单链表的表厂

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Dvvtg9Xo-1619420467829)(D:%5Cimage%5CtyporaImage%5Cimage-20200413164255251.png)]

小结

数组的两个基本操作

  1. 读操作(取值)
  2. 写操作(赋值)

计算数组中给定元素的地址

  1. 确定数组的存储方式(行优先还是列优先)
  2. 计算给定元素的前面的元素个数s
  3. 每个元素的存储空间k
  4. 这个元素地址=起始元素地址(也就是[0]的地址)+s*x

特殊矩阵(讨论的是二维数组)采用压缩存储(存储为一维数组)
压缩存储后依然具有随机存取特性
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SUKz2UqI-1619420467830)(D:%5Cimage%5CtyporaImage%5Cimage-20200413101752775.png)]

计算对称矩阵的压缩存储
注意

  • 确定上三角还是下三角
  • 行优先还是列优先
  • B数组的下标从0还是1开始

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-36wEVdMZ-1619420467831)(D:%5Cimage%5CtyporaImage%5Cimage-20200413102020291.png)]

稀疏矩阵无论是采用三元组还是十字链表都会失去随机存取特性

树和二叉树

树的概念

树的形式化定义:T={D,R}其中D包含n个节点,n=0时为空树

  • 有且仅有一个头节点、树的根节点d0,无前驱节点
  • 其他节点有且仅有一个前驱节点
  • 每个节点有任意个后继节点
  • 如果n>0,其中存在一个唯一节点作为树的根节点(root) ,其余节点可分为m (m≥0)个互不相交的有限子集T1、T2、… Tm,而每个子集本身又是一棵树,称为根节点root的子树
  • 树中所有节点构成一种层次关系

树的逻辑表示:用一颗倒置的树表示树结构

文氏图表示法:用集合的包含关系描述树结构

凹入表示法:使用线段的伸缩关系描述树结构
image-20200331113936674

括号表示法:用字符串表示
根(子树1,子树2(子树3))

树的基本术语

节点的度:节点的子树的个数
树的度:节点的度的最大值
通常称度为m的树为m次树或m叉树

分支节点:度不为0的节点,也称为非终端节点
叶节点:度为0的节点,也称为终端节点
度为1的节点是单分支节点,度为2的节点称为双分支节点

路径:两个节点之间的节点序列称为路径
路径长度:通过的节点数目减一
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CAytESq1-1619420467832)(D:%5Cimage%5CtyporaImage%5Cimage-20200331113316939.png)]

孩子节点:节点的后继节点称为子女节点
双亲节点:当前节点是孩子节点的父母节点
兄弟节点:具有同一双亲节点的孩子节点

子孙节点:一个节点的所有子树中的节点
祖先节点:从根节点到当前节点之前的所有节点
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZFLAO7Mu-1619420467833)(D:%5Cimage%5CtyporaImage%5Cimage-20200331113614597.png)]

节点的层次:根节点为第一层
高度、深度:最大层次

有序数:各节点的子树是按照固定次序从左向右安排的,相对次序不能随意变换
无序树:兄弟节点之间可随意变换相对次序

森林:n个互不相交的树
只要把树的根节点删去就称为森立
反之,只要给n颗独立的树加上一个父节点,则森林变为一棵树

树的性质

  • 节点总数等于度总数加一(加上根节点)
    image-20200331114439477

  • 度为m的树中第i层上至多有m^(i-1)个节点(i≥1)

  • 高度为h的m次树至多有(m^h-1)/(m-1)个节点
    image-20200331114603429

  • 具有n个节点的m次树的最小高度为logm(n(m-1)+1)

树的运算

  • 查找满足某种特定关系的节点,如查找当前节点的双亲节点等
  • 插入或删除某个节点,如在树的当前节点上插入一个新节点或删除当前节点的第i个孩子节点等
  • 遍历树中每个节点(访问每个节点,每个节点只访问一次)
    • 先根遍历:若树不空,则先访问根节点,然后依次先根遍历各棵子树(从上至下)(递归)
    • 后根遍历:若树不空,则先依次后根遍历各棵子树,然后访问根节点(从下至上)(递归)
    • 层次遍历:若树不空,则自上而下、自左至右访问树种每个节点

树的存储结构

  • 双亲存储结构
    typedef struct{
    ElementType data;//节点的值
    int parent; //指向双亲位置
    }PTree[MaxSize];

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JLPdVjZw-1619420467834)(D:%5Cimage%5CtyporaImage%5Cimage-20200331145711558.png)]

  • 孩子链存储结构:每个指针指向一颗子树
    度为多少,则每个节点就有多少个指针
    typedef stuct node{
    ElementType data; //节点的值
    struct node *sons[MaxSons];//指向孩子节点
    }TSonNode;
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xCsjtvrk-1619420467835)(D:%5Cimage%5CtyporaImage%5Cimage-20200331145627312.png)]

  • 孩子兄弟链存储结构:为每个节点这几三个域

    • 一个数据元素域

    • 第一个孩子节点指针域

    • 一个兄弟节点指针域

      typedef struce node{
      ElementType data;//节点的值
      struct tnode *hp;//指向兄弟
      struct tnode *vp;//指向孩子节点
      }TSBNode;

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DP63yIfk-1619420467836)(D:%5Cimage%5CtyporaImage%5Cimage-20200331145410869.png)]

二叉树的概念

递归定义

二叉树是有限的节点集合
这个集合要么空要么由一个根节点和两棵互不相交的称为左子树和右子树的二叉树组成

五种基本形态
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q6ER6XH4-1619420467836)(D:%5Cimage%5CtyporaImage%5Cimage-20200331150841471.png)]

两种特殊的二叉树

  • 满二叉树**(彻底完整)**

    • 所有分支节点都有双分节点
    • 叶节点都集中在二叉树的最下一层

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rRxVRo42-1619420467837)(D:%5Cimage%5CtyporaImage%5Cimage-20200331151129339.png)]

    高度为h的满二叉树,层序编号为2^h-1
    得到满二叉树的定义:高度为h的二叉树恰好有2^h-1个节点

  • 完全二叉树**(去掉最下面一层就是满二叉树)**

    • 最多只有下面两层的节点的度数小于2
    • 最下面一层的叶节点都依次排列在该层最左边的位置上

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tZuYnm5I-1619420467838)(D:%5Cimage%5CtyporaImage%5Cimage-20200331152010420.png)]

二叉树的先序、中序、后序遍历序列
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NDTV4Vy4-1619420467840)(D:%5Cimage%5CtyporaImage%5C20180704200305280.png)]

先(根)序遍历(根左右):A B D H E I C F J K G
中(根)序遍历(左根右):D H B E I A J F K C G
后(根)序遍历(左右根):H D I E B J K F G C A

二叉树性质

  • 非空二叉树上叶节点数等于双分支节点数加1。即:n0=n2+1

    求解二叉树的节点个数问题,通常利用这一性质
    常利用以下关系

    • 节点数n=n0+n1+n2
    • 度之和=n-1
    • 度之和=n1+2*n2
    • 节点数n=n1+2*n2+1
  • 非空二叉树上第i层上至多有2^i-1个节点(i≥1)

  • 高度为h的二叉树至多有2^h-1个节点(h≥1)

  • 完全二叉树性质(含有n个节点)

    • n1=0或者n1=1;若n为奇数则n1=0,若n为偶数则n1=1
    • 若i≤[n/2](向下取整),则编号为i的节点为分支节点,否则为叶节点
    • 除了根节点,每一个节点的编号为i,则它的双亲节点编号为[i/2]
    • 若编号为i的节点有左孩子节点,则左孩子节点的编号为2i
      若编号为i的节点有右孩子节点,则右孩子节点的编号为2i+1
      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-d8Wftw0F-1619420467841)(D:%5Cimage%5CtyporaImage%5Cimage-20200331153152719.png)]

树转换为二叉树

  1. 兄弟节点之间连线
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Np7bS8wH-1619420467842)(D:%5Cimage%5CtyporaImage%5Cimage-20200331153413748.png)]
  2. 保留最左边的孩子和双亲节点的连线(只保留左边第一个孩子节点)
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VIziIDsQ-1619420467843)(D:%5Cimage%5CtyporaImage%5Cimage-20200331153448468.png)]
  3. 顺时针旋转45度,得到二叉树
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aKqQiuS0-1619420467844)(D:%5Cimage%5CtyporaImage%5Cimage-20200331153540140.png)]

多棵树转换为二叉树

  1. 把每一课树转换为二叉树
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rCHlXxU5-1619420467844)(D:%5Cimage%5CtyporaImage%5Cimage-20200331153711011.png)]

  2. 第二课树的根节点作为第一颗树的根节点的右孩子
    第三课树的根节点作为第二棵树的根节点的右孩子
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GrlsMP72-1619420467845)(D:%5Cimage%5CtyporaImage%5Cimage-20200331153848148.png)]

  3. 增加一个虚拟根节点
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BJGxsCDk-1619420467846)(D:%5Cimage%5CtyporaImage%5Cimage-20200331153921604.png)]

  4. 按照一棵树的方法转换为二叉树,再删除增加的节点

二叉树还原为树

  1. 考察每一个节点的右分支节点,把每一个右分支节点和双亲连接起来
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AvfShM1F-1619420467847)(D:%5Cimage%5CtyporaImage%5Cimage-20200331155123035.png)]
  2. 删除右分支线,逆时针旋转45度
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1sXu0uxy-1619420467848)(D:%5Cimage%5CtyporaImage%5Cimage-20200331155148541.png)]

二叉树还原为森林

  1. 考察每个节点的右下节点,提取每一个节点对应的树
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-phJEXFFq-1619420467849)(D:%5Cimage%5CtyporaImage%5Cimage-20200331155249482.png)]
  2. 转换为三棵二叉树
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EO2kfK40-1619420467850)(D:%5Cimage%5CtyporaImage%5Cimage-20200331155310402.png)]
  3. 分别转换为对应的树
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-k3OnuoDl-1619420467851)(D:%5Cimage%5CtyporaImage%5Cimage-20200331155329066.png)]

例题:设计一个二叉树

二叉树的存储结构

完全二叉树:顺序存储结构(下标从1开始)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kyyls7ML-1619420467853)(D:%5Cimage%5CtyporaImage%5Cimage-20200331160727820.png)]

非完全二叉树:首先补齐,看做是完全的,对节点编号
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0IsIISFm-1619420467854)(D:%5Cimage%5CtyporaImage%5Cimage-20200331160844563.png)]

typedef ElementType SqBTree[MaxSize];//用一个数组存储
SqBTree bt = “#ABD#C#E######F”;

二叉树存储结构特点

  • 完全二叉树的顺序存储十分合适

  • 一般的二叉树特别是单分支较多的,只有少数存储单元被利用(退化的二叉树表示每个节点都是单分支的),空间浪费惊人

  • 在顺序结构中,找一个节点的双亲和孩子都很容易

    二叉树的链式存储结构(递归性)
    typedef struct node{
    ElementType data;
    struct node *lchild, *rchild;
    }BTNode;
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DieNBEN5-1619420467855)(D:%5Cimage%5CtyporaImage%5Cimage-20200331161317376.png)]

二叉链特点

  • 除了指针外,较节省空间,占用的存储空间只与树中节点个数有关

  • 找节点的孩子很容易,找双亲不方便

    一棵树采用孩子兄弟链存储结构表示→二叉链

n个节点接→2n个指针域
分支数为n-1→非空指针域有n-1个
空指针域个数=2n-(n-1)=n+1个

二叉树基本运算及其实现

基本运算

  • 创建二叉树CreateBTNoed(*b, *str)根据二叉树括号表示法生成对应二叉链存储结构

    正确的表示串只有四类字符

    • 单个字符:节点的值
    • (:一颗左子树的开始
    • ):一颗子树的结束
    • ,:表示一颗右子树的开始
  • 销毁DestroyBT(*b)销毁并释放空间

  • 查找节点FindNode(*b, x)寻找值域为x的节点并返回指向该节点的指针

  • 找孩子节点LchildNode§和RchildNode§分别求二叉树中节点*p的左右孩子节点

  • 求高度BTNodeDepth(*b)若为空树则高度为0,否则为左子树与右子树中的最大高度+1

  • 输出DispBTNode(*b)以括号表示法输出

二叉树的遍历

  • 先序遍历(根左右)(根节点是首先访问的)
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IPuSH3Zn-1619420467857)(D:%5Cimage%5CtyporaImage%5Cimage-20200414145018805.png)]

  • 中序遍历(左根右)
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vS5ySZwB-1619420467859)(D:%5Cimage%5CtyporaImage%5Cimage-20200414145058701.png)]

  • 后序遍历(左右根)(最后访问根节点)
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R2td9ai8-1619420467860)(D:%5Cimage%5CtyporaImage%5Cimage-20200414145115260.png)]

  • 层次遍历(从上至下从左至右)

    使用队列

    1. 根节点进队
    2. 队不空时循环,从队列中出列一个节点*p,访问它
      1. 若他有左孩子节点,将左孩子节点进队
      2. 若他有右孩子节点,将右孩子节点进队

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uTgEUdaZ-1619420467861)(D:%5Cimage%5CtyporaImage%5Cimage-20200414145618998.png)]
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VqYixfO4-1619420467863)(D:%5Cimage%5CtyporaImage%5Cimage-20200414145650749.png)]

二叉树遍历的应用

计算二叉链存储的二叉树的节点个数(此为后序遍历思想,另外两个也可以)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yD0tIuY1-1619420467864)(D:%5Cimage%5CtyporaImage%5Cimage-20200414150157124.png)]

计算二叉链存储的二叉树的叶子节点个数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-d7rhzHiM-1619420467864)(D:%5Cimage%5CtyporaImage%5Cimage-20200414150302503.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vSuWdRSy-1619420467865)(D:%5Cimage%5CtyporaImage%5Cimage-20200414150349205.png)]

将二叉链存储的二叉树b复制到二叉链存储的二叉树t中
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hFNAiUHT-1619420467866)(D:%5Cimage%5CtyporaImage%5Cimage-20200414150534238.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oISZCbtQ-1619420467867)(D:%5Cimage%5CtyporaImage%5Cimage-20200416170552650.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JmPKwBu4-1619420467867)(D:%5Cimage%5CtyporaImage%5Cimage-20200416170755693.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WuXiLBQt-1619420467868)(D:%5Cimage%5CtyporaImage%5Cimage-20200416170817150.png)]

查找一个节点的层次

展示根结点到所有叶子节点的逆路径

二叉树的构造

中序序列加上层次序列可以唯一确定一颗二叉树

知道中序序列和先序序列或后序序列中的任意一个,即可确定一颗二叉树
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7C1S5lkX-1619420467869)(D:%5Cimage%5CtyporaImage%5Cimage-20200417081940582.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AKBLmQnF-1619420467870)(D:%5Cimage%5CtyporaImage%5Cimage-20200417082655518.png)]

线索二叉树

给每个节点新增左右两个标志位,0表示指向孩子,左1是前驱,右1是后继

线索二叉树会新增一个多余的节点用来连接序列的开始节点和结束节点

建立过程(前驱和后继这里指的是特定序列的遍历过程而不是简单的上下前后关系)

  1. 遍历
  2. 检查当前节点的左右指针域是否为空
    • 如果左指针域为空,将它修改为指向前驱节点的线索
    • 如果右指针域为空,将它修改为指向后继节点的线索

哈夫曼树

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zzjhr4yy-1619420467871)(D:%5Cimage%5CtyporaImage%5Cimage-20200417084446408.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kpD82bdp-1619420467872)(D:%5Cimage%5CtyporaImage%5Cimage-20200417084516772.png)]

构造哈夫曼树的原则

  • 权值越大的叶 节点越靠近根节点
  • 权值越小的叶 节点越远离根节点

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eUnSz3O7-1619420467873)(D:%5Cimage%5CtyporaImage%5Cimage-20200417084828275.png)]

哈夫曼树的特点
n1=0所以n=n0+n2=2*n0-1

小结

树中节点计算方法

  • 任何非空树中,分支数=所有节点度之和,分支数=n-1,n为节点个数
  • 度为m的树中,n=n0+n1+…+nm
  • 度为m的树中,所有节点度之和=n1+2n2+…+mnm

森林T和二叉树B的转换

  • T中一个非叶子节点至少有一个孩子节点,其中有一个最右边的孩子节点s
  • 在B中s没有右孩子→T中n个非叶子节点,B中对应n个没有右孩子节点
  • T的根节点对应B的根节点,它一定是没有右孩子节点→n+1

树的遍历

  • 先根遍历(有递归性)
  • 后根遍历(有递归性)
  • 层次遍历

将树T转换为二叉树B

  • T的先根遍历对应B的先序序列
  • T的后根遍历对应B的中序序列

树的存储结构

  • 双亲存储结构:表示一对一的关系
  • 孩子链存储结构:表示一对多的关系
  • 孩子兄弟链存储结构:树转化为二叉树,对应二叉链

二叉树

n个不同节点构造多少个二叉树
第n个Catalan树[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-id15C7ci-1619420467874)(D:%5Cimage%5CtyporaImage%5Cimage-20200405191907137.png)]

有n个节点并且高度为n的不同形态的二叉树个数是多少
每层一个节点,既可以作为左孩子也可以作为右孩子,有2n-1个二叉树

二叉树中节点计算方法

基本公式

  • 二叉树中所有节点的度≤2
  • 分支数=所有节点度之和,分支数=n-1
  • n=n0+n1+n2
  • 所有节点度之和=n1+2n2
  • no=n2+1

完全二叉树节点计算方法

  • 节点个数为n,树形可以唯一确定
  • 叶子结点个数为n0,树形不能唯一确定
  • n为奇数时,n1=0;n为偶数时,n1=1
  • n0=n2+1
  • 高度h=[log2(n+1)],是n个节点高度最小的二叉树(完全二叉树高度最小,依次排下来)

满二叉树节点计算方法

  • 高度h=log2(n)
  • 高度为h的满二叉树,n=2^h-1,n一定为奇数(根节点+偶数)
  • n0=n2+1
  • n1=0

二叉树的存储结构

  • 顺序存储结构

    按层序编号,从上至下,从左至右,空节点也要计数,最后在数组(从1开始)中用#表示空节点**(结论:本节点为i,双亲节点为i/2,左右子女节点为2i和2i+1)**

  • 二叉链存储结构

    每个节点包含一个值域和两个指针域,两个指针分别指向左右孩子节点(典型的递归数据结构)

    例题:n个节点的二叉树采用二叉链存储,空指针域个数为多少

    1. 每个节点两个指针域,共2n个指针域
    2. 除了根节点,每个节点被一个非空指针指向,所以共有n-1个非空指针域
    3. 空指针域的个数=2n-(n-1)=n+1

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PHWl9l4p-1619420467875)(D:%5Cimage%5CtyporaImage%5Cimage-20200417092152600.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A8DLaIRR-1619420467876)(D:%5Cimage%5CtyporaImage%5Cimage-20200417092227795.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Jv6y8l9r-1619420467876)(D:%5Cimage%5CtyporaImage%5Cimage-20200417092447171.png)]

图的概念

G=(V,E)图
V={0,1,…,n-1}顶点
E={(0,1),(0,4),…,(3,4)}边
也可能是有向图E={<>,<>,…,<>}

术语
一条边(i,j)那么i和j是端点,互为邻接点
<i,j>那么i为起始端点,j为终止端点,互为邻接点

度:边数
入度、出度

n个顶点、e条边,每个顶点的度为di,那么则有e=0.5*Σdi

完全无向图:有n(n-1)/2条边
完全有向图:有n(n-1)条边

稠密图:接近完全图
稀疏图:e<<n(n-1)

子图:边集是子集,节点集也是子集,那么就是原图的子图

路径和路径长度
i到j的一条路径(i,i1,i2,…,j)
路径长度:边的数目
简单路径:开始点和结束点可以相同,其他不相同**(可以回到原点,中间不能交叉)**

回路:开始结束相同节点,则称为回路或环,若是简单路径则是简单回路或简单环

连通:两个顶点之间有路径,则是连通的
若任意都连通,那么是连通图,否则是非连通图
无向图的极大连通子图称为连通分量
任何连通图的连通分量只有一个,非连通图有多个

有向图中,若任意两个顶点都是互相可以连通的,则是强连通图
有向图G中的极大强连通子图称为G的强连通分量。显然,强连通图只有一个强连通分量,即本身。非强连通图有多个强连通分量
寻找强连通分量:找有向环、扩展(若某个节点能到达所有环上节点,反过来也可以的话就加入该节点)
单个孤立的顶点算一个强连通分量

若边可以附带一个对应的数值,则数值称为权,可以表示经过边的距离或花费的代价
边上带有权的图称为带权图,也称作

图的存储结构

使用邻接矩阵存储

A [i] [j]存储对应的边的值,若是无权则0/1,否则就是对应的权的值

一个图的邻接矩阵表示是唯一的
邻接矩阵适合表示稠密图,存储空间为O(n^2)

单链表+数组表示,数组存放各个节点的下属单链表的头结点,单链表的节点就是各个节点的相邻节点
邻接表的显示不唯一,特别适合稀疏矩阵,存储空间为O(n+e)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xQyCOCu3-1619420467877)(D:%5Cimage%5CtyporaImage%5Cimage-20200427091741756.png)]

图的遍历

图的遍历:访问所有顶点,每个顶点仅被访问一次,得到的顶点序列称为图遍历序列

DFS:用栈或递归方式实现(实际用的递归,没有显式调用栈)
确定一个顶点是否访问过,使用visited[i]=0/1,其中1表示已经访问过
时间复杂度是O(n+e)每个顶点每个边都访问过一次
若用邻接矩阵表示,则时间复杂度为O(n^2)

BFS:先进先出,用队列实现
先输出当前节点,然后把当前节点进队列
若队列不空,出队列一个节点,遍历这个节点的单链表,均是先判断,若没有遍历过,就先输出,再入队
邻接表和邻接矩阵的时间和DFS一致

对于非连通图,需要分别遍历每个连通分量才能访问图的所有顶点

判断是否连通,可以先进行一次DFS,然后检查visited数组

图遍历的应用

最小生成树和Prim算法

极大连通子图

  1. 连通图只有一个极大连通子图,就是它本身(是唯一的)
  2. 非连通图有多个极大连通子图(非连通图的极大连通子图叫做连通分量,每个分量都是一个连通图)
  3. 称为极大是因为如果此时加入任何一个不在图的点集中的点都会导致它不再连通

极小连通子图:

  1. 一个连通图的生成树是该连通图顶点集确定的极小连通子图(同一个连通图可以有不同的生成树,所以生成树不是唯一的)(极小连通子图只存在于连通图中)
  2. 用边把极小连通子图中所有节点给连起来,若有n个节点,则有n-1条边。如下图生成树有6个节点,有5条边
  3. 之所以称为极小是因为此时如果删除一条边,就无法构成生成树,也就是说给极小连通子图的每个边都是不可少的
  4. 如果在生成树上添加一条边,一定会构成一个环

由图的全部节点和n-1条边构成

深度优先生成树、广度优先生成树

一个连通图的生成树不一定是唯一的

最小生成树

  • 对于带权连通图G (每条边上的权均为大于零的实数),可能有多棵不同生成树
  • 每棵生成树的所有边的权值之和可能不同
  • 其中权值之和最小的生成树称为图的最小生成树

对于非连通图,每个连通分量的生成树构成连通图的生成森林

Prim算法

  1. 选定一个开始点,加入集合U
  2. 重复下列过程
  3. 选择U集合和V-U集合中的点之间的边的最小值,然后将V-U中的这个点加入U

适用于邻接矩阵存储

时间复杂度O(n^2)

求最小生成树的Kruskal算法

  1. U中加入全部点,VE中无边,也就是把图变成点集
  2. 将边按照权值编号,从小到大编号
  3. 依次选边,只要新加入的边没有和之前的边构成回路就加入

采用邻接矩阵存储

如何解决判断是否会生成回路的问题

采用连通分量编号,比如说初始点为0,vset[0]=0,然后加入点1,那么vset[1]=0,这样只要判断两个点的编号是否相同,如果相同就说明这两个点已经连通了,再加这条边就会导致回路

使用一个数组存储所有边,边类型就是三个int值的结构体,两个节点加上权值

时间复杂度O(elog2(e))

最短路径和Dijkstra算法

带权有向图,简单路径经过的边的权之和定义为路径长度

给定一个源点v,求最短路径,限制权值大于等于0

S存储求得的最短路径的点,U=V-S存储未求得的,最初S只有一个源点v
直到U为空,则算法结束

时间复杂度O(n^2)

求最短路径的Floyd算法

O(n^3)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rbBFUASx-1619420467878)(D:%5Cimage%5CtyporaImage%5Cimage-20200511161321586.png)]

拓扑排序

若一个有向图中的顶点不能排成一个拓扑序列,则可断定该有向图含有顶点数大于1的强连通分量

求关键路径

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p1zJ8GmP-1619420467879)(D:%5Cimage%5CtyporaImage%5Cimage-20200511162104326.png)]

小算法解决大问题

小结

哈夫曼树就是没有度为1的节点的树

注意强连通图只是有路径,不是一定有边

查找

B树计算高度时需要计入最底层的外部节点
外部节点个数等于内部关键字n+1

内排序

小结

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cz9eywXH-1619420467880)(D:%5Cimage%5CtyporaImage%5Cimage-20200605102412977.png)]

期末复习

线性探测法:哈希冲突时候从冲突点往后找,都找不到再从头开始找

关键路径是源点到汇点的最长路径

哈夫曼树的构造算法

循环队列,rear向前

空串也是字串

串从1开始计数

三元组除了数组还有三个属性,行数、列数和非零元素个数

三元组是按行为主序列排序,所以转置不能简单地仅仅互换m和n

哈夫曼树没有度为1的节点

哈夫曼树的特点
n1=0所以n=n0+n2=2*n0-1

快速排序最坏时间复杂度是O(n^2)

简单选择排序、堆排序、希尔排序、快速排序不稳定

. 重复下列过程
3. 选择U集合和V-U集合中的点之间的边的最小值,然后将V-U中的这个点加入U

适用于邻接矩阵存储

时间复杂度O(n^2)

求最小生成树的Kruskal算法

  1. U中加入全部点,VE中无边,也就是把图变成点集
  2. 将边按照权值编号,从小到大编号
  3. 依次选边,只要新加入的边没有和之前的边构成回路就加入

采用邻接矩阵存储

如何解决判断是否会生成回路的问题

采用连通分量编号,比如说初始点为0,vset[0]=0,然后加入点1,那么vset[1]=0,这样只要判断两个点的编号是否相同,如果相同就说明这两个点已经连通了,再加这条边就会导致回路

使用一个数组存储所有边,边类型就是三个int值的结构体,两个节点加上权值

时间复杂度O(elog2(e))

最短路径和Dijkstra算法

带权有向图,简单路径经过的边的权之和定义为路径长度

给定一个源点v,求最短路径,限制权值大于等于0

S存储求得的最短路径的点,U=V-S存储未求得的,最初S只有一个源点v
直到U为空,则算法结束

时间复杂度O(n^2)

求最短路径的Floyd算法

O(n^3)

[外链图片转存中…(img-rbBFUASx-1619420467878)]

拓扑排序

若一个有向图中的顶点不能排成一个拓扑序列,则可断定该有向图含有顶点数大于1的强连通分量

求关键路径

[外链图片转存中…(img-p1zJ8GmP-1619420467879)]

小算法解决大问题

小结

哈夫曼树就是没有度为1的节点的树

注意强连通图只是有路径,不是一定有边

查找

B树计算高度时需要计入最底层的外部节点
外部节点个数等于内部关键字n+1

内排序

小结

[外链图片转存中…(img-cz9eywXH-1619420467880)]

期末复习

线性探测法:哈希冲突时候从冲突点往后找,都找不到再从头开始找

关键路径是源点到汇点的最长路径

哈夫曼树的构造算法

循环队列,rear向前

空串也是字串

串从1开始计数

三元组除了数组还有三个属性,行数、列数和非零元素个数

三元组是按行为主序列排序,所以转置不能简单地仅仅互换m和n

哈夫曼树没有度为1的节点

哈夫曼树的特点
n1=0所以n=n0+n2=2*n0-1

快速排序最坏时间复杂度是O(n^2)

简单选择排序、堆排序、希尔排序、快速排序不稳定

堆排序空间复杂度为O(1)

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值