GESP6级集训课第1讲

一、线性数据结构

1. 栈

1.1 概念

栈:只能在某一端插入和删除的线性数据结构(和羽毛球筒一样
栈顶:进行删除和插入的一端
栈底:不进行删除和插入的一端
进栈:放入元素
出栈:取出元素
满栈:栈的元素填满整个栈
空栈:栈中无元素
栈的特点:先进后出,后进先出(FILO)
下溢:空栈时出栈
上溢:满栈时进栈

1.2 程序

1.2.1 STL

头文件:

#include<stack>

定义格式:

stack<数据类型>栈名;

基本操作:

方法功能
.push(x) x x x 进栈
.pop()出栈
.top()栈顶元素
.empty()判空
.size()元素个数
1.2.2 数组模拟

定义格式:

const int N=100;//栈的大小
int top=0;//栈顶指针
数据类型 s[N+1];

基本操作:

方法功能
s[++top]=x x x x 进栈
top--出栈
s[top]栈顶元素
1.2.3 链式栈

概念:
链栈(链式栈)是一种基于链式存储结构(单链表)实现的栈。与顺序栈不同,链式栈的栈顶指针指向链表的头部。由于栈的操作仅限于栈顶,因此栈顶放在单链表的头部。在链栈中,栈顶元素的插入和删除操作都在链表的头部进行。

基本操作:

  • 初始化栈:创建一个空链式栈,栈顶指针指向空
  • 进栈:在链表头部插入新结点
  • 出栈:删除链表头部结点
  • 栈顶元素:返回链表头部的结点数据
  • 判空:判断栈顶指针是否为空

1.3 应用

1.3.1 括号配对

具体方法:

  1. 遍历表达式中每个字符,遇到左括号时入栈
  2. 遇到右括号时与栈顶元素匹配并出栈
  3. 若匹配成功则继续,若不匹配或栈空则表示括号不匹配
  4. 遍历结束后,若栈为空则括号匹配正确,否则错误
1.3.2 进制转换

具体方法:

  1. 将十进制数除以要转的进制,得到商和余数
  2. 将余数进栈
  3. 重复前两步直到商为 0 0 0
  4. 依次出栈,得到的序列为最终表示结果

利用原理:因为最终时倒取余,可以用栈的后进先出特性来解决

1.3.3 前缀表达式求值

具体方法:

  1. 从右到左扫描
  2. 遇数进栈
  3. 遇号将栈顶两个元素计算,运算结果放入栈顶(栈顶元素 操作符 第二个元素)
1.3.4 后缀表达式求值

具体方法:

  1. 从左到右扫描
  2. 遇数进栈
  3. 遇号将栈顶两个元素计算,运算结果放入栈顶(第二个元素 操作符 栈顶元素)

2. 队列

2.1 概念

队列:先进先出的先行数据结构,允许在一段插入,另一端删除(和排队一样
队头:离开队列的一端
队尾:进入队列的一端
上溢:队列满继续入队
假上溢:队列存在可用位置时发生的上溢

2.2 程序

2.2.1 STL

头文件:

#include<queue>

定义格式:

queue<数据结构>队列名;

基本操作:

方法功能
.push(x) x x x 入队
.pop()出队
.front()队头元素
.back()队尾元素
.empty()判空
.size()元素个数
2.2.2 数组模拟

定义格式:

const int N=100;//队列的大小
int head=0,tail=0;//队头队尾指针,tail指向哨兵位置
数据类型 q[N+1];

基本操作:

方法功能
s[tail++]=x x x x 入队
head++出队
tail-head元素个数
tail==head判空

2.3 应用

2.3.1 循环队列

概念:能够循环利用数组空间的队列
基本操作:

方法功能
q[tail]=x,tail=(tail+1)%N x x x 入队
head=(head+1)%N出队
(tail-head+N)%N元素个数
tail==head判空
(tail+1)%N==head判满

二、树形数据结构

1. 树的概念

树:一种抽象的非线性数据结构,用来模拟具有树状结构性质的数据集合
树的特点:由 n n n n ≥ 0 n\ge0 n0)个结点组成的具有分支和层次特性的数据集合。


直接前驱:父结点
直接后继:子结点
根结点:没有直接前驱,只有直接后继的结点
叶结点:度为 0 0 0 的结点
兄弟结点:具有相同父结点的结点


层次:从根开始,根为第 1 1 1 层,根的子结点为第 2 2 2 层,以此类推
深度:根结点深度为 0 0 0 1 1 1,根的子结点为父结点的深度 + 1 +1 +1
子树:以树中某一个结点为根,该结点和其所有后代结点构成的一棵树
森林: m m m m ≥ 0 m\ge0 m0)棵互不相交的树的集合


结点的度:拥有的子树个数
树的度:一棵树中所有结点的度的最大值为树的度


树是一种特殊类型的无环连通图,任何两个顶点之间都有一条唯一的简单路径。


结点的权:人为赋予的一个数,通常代表结点的重要性
结点的带权路径长度:从根结点到该结点的路径长度与该结点权重的乘积
数的带权路径长度:树中所有叶结点的带权路径长度之和(WPLWeighted Path Length

2. 树的性质

  1. 树中的结点数等于所有结点的度之和 + 1 +1 +1,即
    n = 1 + 1 × n 1 + 2 × n 2 + ⋯ n=1+1\times n_1+2\times n_2+\cdots n=1+1×n1+2×n2+
  2. 树中的结点数等于所有结点个数总和,即
    n = n 0 + n 1 + n 2 + ⋯ n=n_0+n_1+n_2+\cdots n=n0+n1+n2+
  3. n n n 个结点的树中有 n − 1 n-1 n1 条边

3. 二叉树

3.1 概念

二叉树(binary tree,BT)是一种特殊的树形结构,二叉树的每个结点最多有两个子结点,每个结点的子结点分别成为左孩子、右孩子,它的两棵子树分别成为左子树、右子树。

3.2 形态

  • 空二叉树
  • 只有根结点
  • 只有左子树
  • 左右子树都有
  • 只有右子树

3.3 性质

  1. 非空二叉树的叶结点数等于度为 2 2 2 的结点数 + 1 +1 +1,即
    n 0 = n 2 + 1 n_0=n_2+1 n0=n2+1
  2. 非空二叉树第 k k k 层上至多有 2 k − 1 2^{k-1} 2k1 个结点( k ≥ 1 k\ge1 k1
  3. 高度为 h h h 的二叉树之多有 2 h − 1 2^h-1 2h1 个结点( h ≥ 1 h\ge1 h1

3.4 特殊二叉树

3.4.1 满二叉树

满二叉树:一棵高度为 h h h 且有 2 h − 1 2^h-1 2h1 个结点的二叉树。

约定根结点编号为 1 1 1,自上而下,自左向右编号。对于编号为 i i i 的结点,若有父结点则其父结点编号为 i 2 \frac{i}{2} 2i,若有左孩子则左孩子为 2 i 2i 2i,若有右孩子则右孩子为 2 i + 1 2i+1 2i+1。可以使用数组来存储一颗满二叉树。即

i/2
i
2i
2i+1
3.4.2 完全二叉树

完全二叉树:一棵高度为 h h h、有 n n n 个结点,且所有结点都与相同高度的满二叉树编号对应时的二叉树。所以也可以使用数组来存储一颗完全二叉树。

特点:

  1. 叶结点只可能在层次最大的两层上出现,对于最大层次中的叶结点,都依次排列在该层最左边的位置上。
  2. 若有度为 1 1 1 的结点,则只可能有一个,且该结点只有左孩子,没有右孩子

性质:

  1. 按层编号后,一旦出现某结点(编号为 i i i)为叶结点或只有左孩子时,则编号大于 i i i 的结点均为叶结点
  2. n n n 为奇数则没有度为 1 1 1 的结点,叶结点数量等于 ⌈ n 2 ⌉ \lceil \frac{n}{2} \rceil 2n;若 n n n 为偶数则编号为 n 2 \frac{n}{2} 2n 的结点只有左孩子没有右孩子,叶结点数量等于 n 2 \frac{n}{2} 2n

4. 哈夫曼树

4.1 定义

在含有 n n n 个带权叶结点的二叉树中,WPL 最小的二叉树被成为哈夫曼树,也称最优二叉树。

4.2 构造

算法原理:贪心算法
初始状态:对于给定的 n n n 个权值,每个权值作为一个独立的结点,形成 n n n 个单结点树。
构造过程:

  1. 从当前的森林中选取两个根结点权值最小的树(或结点)。
  2. 将这两个树合并为一棵新的二叉树,新树的根结点的权值为两个子树根权值之和。
  3. 将新树放回森林中,同时删除原来两个独立的树。
  4. 重复上述步骤,直到森林中只剩下一棵树为止。

最终结果:剩下的那棵树就是哈夫曼树,其叶结点所代表的权值对应着原始输入的各个权重,并且树的带权路径长度达到最小。

4.3 性质

  • 每个初始结点都会成为哈夫曼树的叶结点,且权值越小的结点到根结点的路径长度越大;
  • 哈夫曼树的总结点数为 2 n − 1 2n-1 2n1
  • 哈夫曼树中不存在度为 1 1 1 的结点
  • 哈夫曼树不唯一,但 WPL 必然相同且最小

4.4 哈夫曼编码

4.4.1 性质
  • 哈夫曼编码是一种无损编码
  • 哈夫曼编码是变长码
  • 哈夫曼编码基于频率排序实现
  • 哈夫曼编码是最优前缀码
  • 哈夫曼编码不是唯一码
4.4.2 原理

让出现频率高的信息编码长度短,让出现频率低的信息编码长度长,从而达到哈夫曼编码整体最短。因此哈夫曼编码使用的是贪心算法的思想。

4.4.3 方法
  • 统计待编码的字符出现的频率,并排列。
  • 反复取出两个频率最低的节点,将它们合并为一个新节点,频率为两个节点频率之和,将新节点重新排列。
  • 重复步骤,直到只剩下一个节点,即构建完成的哈夫曼树。
  • 通过遍历哈夫曼树,从根节点到每个叶子节点的路径上的左子树赋值为 0 0 0,右子树赋值为 1 1 1,得到每个字符的哈夫曼编码。
  • 使用哈夫曼编码将原始数据进行编码和解码。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值