数据结构培训教程
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
• 自平衡树
平衡树
• 源自普通的排序二叉树(二叉排序树,BST) • 平衡树的纯手写版现今比赛比较少用 • 没有用到高级功能的话一般用set或map代
poi9806相等的单词
• 让二进制串a,b,c,d,e分别为长度为4,2,4 ,4,2的5个变量。
• 考虑以下等式:1bad1=acbe。 • 问有多少种变量取值使得等式成立
poi9806
• 1bad1=acbe
• 位置组: • (1,4,7,12),(2,5,9),(3,6,10),(8),(11) • 这个等式有16种不同的解答方案。
排序二叉树
• 又称二叉搜索树,二叉检索树 • 具有以下性质 对于任意一个父亲节点的值k 它的左子树所有节点的值都<=k 它的右子树所有节点的值都>=k • 基本操作 插入、删除、查找
平衡问题
• 当排序二叉树的高度接近logn的时候,它是 良态的,插入、删除、查找O(logn)
• 当排序二叉树的高度接近n的时候,比较像 一个链,O(n)
其他排序法
• 堆排序O(nlogn) • 基数排序 • ……..
稳定性
• 选择排序不稳定 • 插入排序稳定 • 快速排序不稳定 • 归并排序稳定 • 堆排序不稳定
哈希表
• Hash table,也叫散列表 • 是根据关键码值(Key value)而直接进行访
问的数据结构。也就是说,它通过把关键 码值映射到表中一个位置来访问记录,以 加快查找的速度。 • Hash函数
优先队列
• 一般支持的操作: • 1.支持插入,删除元素(间接说明支持修改
) • 2.支持查找最大或最小元素 • *3.不支持合并操作,但左偏树等可并优先
队列仍可以支持 • 注意:所谓的支持的操作是指复杂度在线
性以下可以完成,例如O(logN),O(1),也有 可以是O(N^0.5)
优先队列
• 一般来说优先队列就是用堆 • 例子 • dijkstra算法用优先队列优化O((n+m)logn) • 动态维护中位数问题,一个集合,要支持
排序算法
• 插入排序O(n^2) 在已有有序序列中每次插入一个元素 • 选择排序O(n^2) 给每个位置选择当前元素最大(最小) • 归并排序O(nlogn) 把序列一分为二,对有序序列归并
快速排序
• 基本思想 任取一个数把数列分成两段——它左边的 数都比它小,它右边的数都比它大
此时这个数就在目标序列中它的位置上 对两个子段分别进行排序 • 时间复杂度 最坏O(n^2),期望O(nlogn)
}
冲突
• return h % M; • 一般来说M是一个大质数 • 冲突的解决 开散列法 闭散列法
几个例子
• 给一个学生信息的列表,根据姓名查询学 生信息
• 走迷宫的时候判断某个格子是否走过
Hash表
• 推荐阅读 2005年IOI国家集训队论文 李羽修《Hash函数的设计优化》
• 另外为图方便,C++里用map<T1,T2>(实 际是红黑树)来实现hash的映射编程上会 比较方便
• 例如下图的一个合法遍历为: 1 3 4 6 5 2 7
隔三wenku.baidu.com历
• 算法: • 由于规模大,考虑进行构造而不是搜索.由于是一般
的树,可以模仿二叉树遍历的方法. • 首先深度优先遍历无向图成为一棵多叉树,并标上
深度(depth),然后对每个结点x,考虑它的深度 depth: • 如果depth为奇数,那么对结点x进行先序遍历; 如果depth为偶数,那么对结点x进行后序遍历。 • 用数学归纳法可以得证。
并查集
• 查找一个元素在哪个集合中 • 合并两个集合 • 用森林实现并查集,用树根表示集合 • 查找 查找某个元素所在树的树根,同时压缩路径 • 合并 较小的集合树根的父亲设为较大集合的根
并查集
• 时间效率O(m*f(m,n)), • f是Ackermann函数的某个反函数,一般认
为小于5 • 应用 查找两个元素是否在同一个集合中
数据结构培训教程
2020年4月22日星期三
树和森林
• 连通无回路的无向图 • 树的递归定义 一棵树要么为空,要么由根和它的子树组成 • 森林——树的集合
二叉树
• 左子树、右子树
• 前序遍历 • 中序遍历 • 后序遍历
遍历
• 练习
已知前序遍历和中序遍历的序列,求后序 遍历的序列
思考:隔三遍历
• 隔三遍历:即遍历得到的序列(a1,a2,...,an)满 足:序列中任意两个相邻点在树上的距离小 于或等于3.
完全二叉树
• 除了底层,其他层都达到最大子节点个数 • 自顶向下,同层从左往右编号0,1,2…,n-1 • 对任意序号i i的父节点是(i-1)/2 i的左子节点i*2+1 i的右子节点i*2+2
堆
• 以小根堆为例 • 所有父节点的值都小于等于子节点的值 • 向上维护(插入),O(logn) • 向下维护(删除),O(logn) • 一般用完全二叉树实现
问题
• 总共输入n(n<1000000)个不同的数,每个 数介于(0-1000000)之间,输入过程中会不 定时修改某些数的大小,继续维持堆的性 质。
带HASH的堆
• 根据题中数据范围以及两两不等。 • A[i]代表元素大小为i的元素在堆中的位置 • 这样修改的复杂度降为O(1) • 修改后调整复杂度为O(log n) • 总修改的复杂度为O(log n) • 应用 SPFA
字符串的hash函数
int ELFhash(char *key){ unsigned long h=0; while(*key){ h=(h<<4)+*key++; unsigned long g=h & 0Xf0000000L; if (g) h^=g>>24; h &= ~g; } return h % M;
插入操作和求当前中位数的操作,容易想 到的是编程极其复杂的平衡树,但用优先 队列会比较方便
哈夫曼树
• 问题: • 给定10^4个数,每次合并其中两个数a,b,
合并代价为a+b,现在求合并代价总和的最 小值
Huffman树
• 每次合并当前数组中最小的两个数 • Huffman树的由来 • 一种贪心的思想 • 暴力复杂度O(n^2) • 用优先队列优化,复杂度为O(nlogn)
平衡树
• 源自普通的排序二叉树(二叉排序树,BST) • 平衡树的纯手写版现今比赛比较少用 • 没有用到高级功能的话一般用set或map代
poi9806相等的单词
• 让二进制串a,b,c,d,e分别为长度为4,2,4 ,4,2的5个变量。
• 考虑以下等式:1bad1=acbe。 • 问有多少种变量取值使得等式成立
poi9806
• 1bad1=acbe
• 位置组: • (1,4,7,12),(2,5,9),(3,6,10),(8),(11) • 这个等式有16种不同的解答方案。
排序二叉树
• 又称二叉搜索树,二叉检索树 • 具有以下性质 对于任意一个父亲节点的值k 它的左子树所有节点的值都<=k 它的右子树所有节点的值都>=k • 基本操作 插入、删除、查找
平衡问题
• 当排序二叉树的高度接近logn的时候,它是 良态的,插入、删除、查找O(logn)
• 当排序二叉树的高度接近n的时候,比较像 一个链,O(n)
其他排序法
• 堆排序O(nlogn) • 基数排序 • ……..
稳定性
• 选择排序不稳定 • 插入排序稳定 • 快速排序不稳定 • 归并排序稳定 • 堆排序不稳定
哈希表
• Hash table,也叫散列表 • 是根据关键码值(Key value)而直接进行访
问的数据结构。也就是说,它通过把关键 码值映射到表中一个位置来访问记录,以 加快查找的速度。 • Hash函数
优先队列
• 一般支持的操作: • 1.支持插入,删除元素(间接说明支持修改
) • 2.支持查找最大或最小元素 • *3.不支持合并操作,但左偏树等可并优先
队列仍可以支持 • 注意:所谓的支持的操作是指复杂度在线
性以下可以完成,例如O(logN),O(1),也有 可以是O(N^0.5)
优先队列
• 一般来说优先队列就是用堆 • 例子 • dijkstra算法用优先队列优化O((n+m)logn) • 动态维护中位数问题,一个集合,要支持
排序算法
• 插入排序O(n^2) 在已有有序序列中每次插入一个元素 • 选择排序O(n^2) 给每个位置选择当前元素最大(最小) • 归并排序O(nlogn) 把序列一分为二,对有序序列归并
快速排序
• 基本思想 任取一个数把数列分成两段——它左边的 数都比它小,它右边的数都比它大
此时这个数就在目标序列中它的位置上 对两个子段分别进行排序 • 时间复杂度 最坏O(n^2),期望O(nlogn)
}
冲突
• return h % M; • 一般来说M是一个大质数 • 冲突的解决 开散列法 闭散列法
几个例子
• 给一个学生信息的列表,根据姓名查询学 生信息
• 走迷宫的时候判断某个格子是否走过
Hash表
• 推荐阅读 2005年IOI国家集训队论文 李羽修《Hash函数的设计优化》
• 另外为图方便,C++里用map<T1,T2>(实 际是红黑树)来实现hash的映射编程上会 比较方便
• 例如下图的一个合法遍历为: 1 3 4 6 5 2 7
隔三wenku.baidu.com历
• 算法: • 由于规模大,考虑进行构造而不是搜索.由于是一般
的树,可以模仿二叉树遍历的方法. • 首先深度优先遍历无向图成为一棵多叉树,并标上
深度(depth),然后对每个结点x,考虑它的深度 depth: • 如果depth为奇数,那么对结点x进行先序遍历; 如果depth为偶数,那么对结点x进行后序遍历。 • 用数学归纳法可以得证。
并查集
• 查找一个元素在哪个集合中 • 合并两个集合 • 用森林实现并查集,用树根表示集合 • 查找 查找某个元素所在树的树根,同时压缩路径 • 合并 较小的集合树根的父亲设为较大集合的根
并查集
• 时间效率O(m*f(m,n)), • f是Ackermann函数的某个反函数,一般认
为小于5 • 应用 查找两个元素是否在同一个集合中
数据结构培训教程
2020年4月22日星期三
树和森林
• 连通无回路的无向图 • 树的递归定义 一棵树要么为空,要么由根和它的子树组成 • 森林——树的集合
二叉树
• 左子树、右子树
• 前序遍历 • 中序遍历 • 后序遍历
遍历
• 练习
已知前序遍历和中序遍历的序列,求后序 遍历的序列
思考:隔三遍历
• 隔三遍历:即遍历得到的序列(a1,a2,...,an)满 足:序列中任意两个相邻点在树上的距离小 于或等于3.
完全二叉树
• 除了底层,其他层都达到最大子节点个数 • 自顶向下,同层从左往右编号0,1,2…,n-1 • 对任意序号i i的父节点是(i-1)/2 i的左子节点i*2+1 i的右子节点i*2+2
堆
• 以小根堆为例 • 所有父节点的值都小于等于子节点的值 • 向上维护(插入),O(logn) • 向下维护(删除),O(logn) • 一般用完全二叉树实现
问题
• 总共输入n(n<1000000)个不同的数,每个 数介于(0-1000000)之间,输入过程中会不 定时修改某些数的大小,继续维持堆的性 质。
带HASH的堆
• 根据题中数据范围以及两两不等。 • A[i]代表元素大小为i的元素在堆中的位置 • 这样修改的复杂度降为O(1) • 修改后调整复杂度为O(log n) • 总修改的复杂度为O(log n) • 应用 SPFA
字符串的hash函数
int ELFhash(char *key){ unsigned long h=0; while(*key){ h=(h<<4)+*key++; unsigned long g=h & 0Xf0000000L; if (g) h^=g>>24; h &= ~g; } return h % M;
插入操作和求当前中位数的操作,容易想 到的是编程极其复杂的平衡树,但用优先 队列会比较方便
哈夫曼树
• 问题: • 给定10^4个数,每次合并其中两个数a,b,
合并代价为a+b,现在求合并代价总和的最 小值
Huffman树
• 每次合并当前数组中最小的两个数 • Huffman树的由来 • 一种贪心的思想 • 暴力复杂度O(n^2) • 用优先队列优化,复杂度为O(nlogn)