数据结构
线性结构
堆栈
引入:后缀表达式,从左往右扫描,逐个处理运算数和运算符号。
特点:只在一端(栈顶Top)做插入删除,先入后出(Last In First Out)
入栈(Push):插入数据
出栈(Pop):删除数据
使用例
1.一个数组实现两个堆栈
1 |
|
2.中缀表达式转换为后缀表达式
从头到尾读取中缀表达式的每个对象,对不同对象按不同的情况处理。
- 运算数:直接输出;
- 左括号:压入堆栈;
- 右括号:将栈顶的运算符弹出并输出,直到遇到左括号( 出栈,不输出);
- 运算符:
• 若优先级大于栈顶运算符时,则把它压栈;
• 若优先级小于等于栈顶运算符时,将栈顶运算符弹出并输出;再比较新的栈顶运算符,直到该运算符大于栈顶运算符优先级为止,然后将该运算符压栈; - 若各对象处理完毕,则把堆栈中存留的运算符一并输出。
3.堆栈的其他应用:
- 函数调用及递归实现
- 深度优先搜索
- 回溯算法
- 。。。
队列
队列(Queue): : 具有一定 操作 约束的线性表
插入和删除操作 :只能在 一端插入 ,而在 另一端删除
- 数据插入 :入队列(AddQ)
- 数据删除 :出队列(DeleteQ)
- 先来先服务
- 先进先出:FIFO
队列的顺序存储实现
队列的顺序存储结构通常由一个一维数组和一个记录队列头元
素位置的变量front以及一个记录队列尾元素位置的变量rear组成。
1 |
|
特性:front=rear时堆栈空或满。
顺环序列:
数组最后一位连接第一位。
区分堆栈空或满所使用的方法:
引入变量标记:Size(记录录入数据总数)或Tag(记录最后一次的操作是录入还是删除)。
让数组空一个出来:仅堆栈满时满足rear+1=front,仅堆栈空时满足front=rear。
在顺环序列中的具体实现:堆栈满:
1.入队列
1 | void AddQ( Queue PtrQ, ElementType item) |
2.出队列
1 | ElementType DeleteQ ( Queue PtrQ ) |
队列的链式存储实现
1 | struct Node{ |
不带头结点的链式队列出队操作的一个示例:
1 | ElementType DeleteQ ( Queue PtrQ ) |
应用: 多项式加法运算
采用不带头结点的单向链表 ,按照指数递减的顺序排列各项
1 | struct PolyNode { |
算法思路 :两个指针P1 和P2 分别指向这两个多项式第一个结点 ,不断循环,赋值给结果多项式:
- P1->expon==P2->expon: 系数相加,若结果不为0,则作为结果多项式对应项的系数。同时,P1和P2都分别指向下一项;
- P1->expon>P2->expon: 将P1的当前项存入结果多项式,并使P1指向下一项;
- P1->expon
expon: 将P2的当前项存入结果多项式,并使P2指向下一项; - 当某一多项式处理完时,将另一个多项式的所有结点依次复制到结果多项式中去。
1 | Polynomial PolyAdd (Polynomial P1, Polynomial P2) |
树
查找 (Searching)
静态查找 :集合中记录是固定的
- 没有插入和删除操作,只有查找
动态查找 :集合中记录是动态变化的
- 除查找,还可能发生插入和删除
静态查找
方法1:顺序查找(低效率)
顺序查找算法的时间复杂度为O(n)。
方法2 :二分查找(Binary Search)
- 假设n 个数据元素的关键字满足有序( 比如:小到大) )
- 并且是连续存放( 数组 ),那么可以进行二分查找
1 | int BinarySearch ( StaticTable * Tbl, ElementType K) |
二分查找算法具有对数的时间复杂度O(logN)。
判定树
*ASL:平均成功查找次数,需要的查找次数x个数(总和)/总数
树的定义
树T的根为A。
树的度:3(A,D)
树的深度:4(L,M在最大层次)
树的表示
儿子- 兄弟表示法
FirstChild:指向子节点
NextSibling:指向下一个兄弟节点
二叉树:度为2的树,即每个结点指针最多两个。
二叉树
二叉树T :一个有穷的结点集合。这个集合空可以为空。若不为空,则它是由根结点和称为其左子树TL和树右子树TR的两个不相交的二叉树组成。
二叉树具体五种基本形态
区别于一般度为2的树,二叉树的子树有左右顺序之分
特殊二叉树
不是完全二叉树
二叉树几个重要性质
二叉树的抽象数据类型定义
二叉树的存储结构
对于一般二叉树,将其补充成完全二叉树
二叉树的遍历
二叉树的非递归遍历
层序遍历
二叉树遍历的核心问题:二维结构的线性化
- 从结点访问其左、右儿子结点
- 访问左儿子后,右儿子结点怎么办?
- 需要一个存储结构保存暂时不访问的结点
- 存储结构:堆栈、队列
二叉搜索树
平衡二叉树
本质仍是搜索树
RR旋转:(结点上数字为平衡因子)
当插入结点作为被破坏结点A的右子树的右子树的子树时(其本身可以为左子树或右子树),把被破坏结点的右子树B代替被破坏结点A的位置,被破坏结点A作为其左子树,其余结点BL按照ST(查找树)标准调整。
LL旋转:
同理。
调整先从子树开始调整。
LR旋转
将A,B,C中的中间值C代替A位置,其余ST调整。
RL旋转
同理。
堆:对最大值或最小值进行处理。
采用完全二叉树表示堆:
Elements数组从下标为1的位置开始存储,固MaxSize+1。
最大堆的插入
T(N)=O(logN)
左儿子:2P;右儿子:2P+1。
Child!=H->Size:排除最后一个结点。
Parent*2<=H->Size:判断P(Parent)结点是否有左儿子。
哈夫曼树与哈夫曼编码
哈夫曼树的构造:每次把权值最小的两棵二叉树合并
集合及运算
排序
简单排序
时间复杂度下界
希尔排序
堆排序
PercDown函数:向下过滤
归并排序:有序子列的归并
快速排序
表排序
基数排序
排序算法的比较
图
图的遍历
最短路径问题
最小生成树问题
拓扑排序
关键路径问题:由不允许延误的活动组成的路径
散列查找
散列表
散列函数的构造方法
冲突处理方法
散列表的性能分析
应用:文件中单词词频统计
串的模式匹配
KMP算法