数据结构与算法小结(2)
来源:互联网 发布:windows同步软件 编辑:程序博客网 时间:2024/06/03 21:31
一、二叉搜索树
1.BST试图解决的问题:
高效的兼顾静态的查找和动态的增删。在基本的数据结构中 数组通过寻秩可实现高效的查找,但增删效率低; 向量通过寻位置访问,增删高效,但查找低效,而且因为增删前通常都需要先找到对应的元素,这使得其效果更差。改进思路是改变访问方式,使用寻关键码访问。引入关键码,将数据项与其关键码绑定,统一的表示为词条的形式,根据关键码来访问元素,用数据项保存元素。关键码需支持比较器和判等器。
2.BST的特性
顺序性:任一节点均不小于/不大于其左/右后代单调性:BST的中序遍历序列必然单调非降。BST的充要条件BST中,根节点中序遍历的后继为右子树中最小的节点
3.BST的接口实现
查找:类似二分查找,最后得到匹配节点(无匹配项时为空的哨兵节点)以及其父节点_hot。插入:查找,无雷同元素则将待插入节点作为找到的_hot节点的子节点插入。删除:先查找,找到的节点只有一个子树时,直接删除,用其子树替换;若有两个子树,找到该节点的后继(比该节点大的最小的节点,该点必定只有一个子树),先交换这两个点,再删除需删除的节点。
删除的算法实现:Template <typename T> static BinNodePosi(T)removeAt( BinNodePosi(T) & x,BinNodePosi(T) & hot ){ BinNodePosi(T) w = x; //实际被摘除的节点,初值同x BinNodePost(T) succ = NULL; //实际被删除节点的接替者 if(!hasLChild(*x)){ succ = x = x->rChild; //情形一:待删除节点没有左孩子,直接以右孩子接替(右孩子可为空)。 }else if(!hasChild(*x)){ succ = x = x->lChild; //这段代码不会走到,没有孩子时,肯定没有左孩子,会走情形一 }else{ //情形二:待删除节点有左右孩子 w = w->succ(); //先找到在中序遍历中,待删除节点的后继(即比待删节点大的最小节点) swap(x->data,w->data); //交换待删节点与其后继的值 BinNodePosi(T) u = w->parent; //找后继是先找右孩子,然后沿左侧链到底,所以此处有此判断。需注意的是,左侧链到底,所以其必定没有左孩子,可能由右孩子 (u == x ? u->rChild :u->lChild) = succ = w->rChild; } hot = w->parent; if(succ){ //若之前找到的后继有右孩子 succ->parent = hot; //因为其一定没有左孩子,所以可以通情形一处理。 } release(w->data); release(w); return succ;}
4.适度平衡
理想平衡:叶节点只能出现在最底部的两层,即完全树甚至满树。适度平衡:高度渐进地不超过o(logn),即可称作适度平衡。即平衡二叉搜索树BBST。 对于每个节点,其子节点数为偶数,即要么没有子节点,要么有两个子节点。等价BST:上下可变(父子关系可颠倒),左右不乱(中序遍历序列不变,全局保持单调非降)。 等价变换、旋转调整。zig顺时针,zag逆时针
适度平衡的例子之AVL树:
AVL树:所有节点左右子树的高度只差不大于1。 高度为h的AVL树,至少包含S(h) = fib(h + 3) - 1个节点。 由n的节点构成的AVL树,高度至多为o(logn)AVL实现: 每个节点需维护一个平衡因子,其值为左子树树高减去右子树树高,每次增删节点时,都需向上冒泡计算。所以,每个节点还需维护一个记录其树高的成员变量。 插入:若要失衡,共有四种情况,因对称的重复,可分两种情况讨论 1.左(右)侧链,此时单旋即可使子树高度复原 2.Z字链,此时双旋也可使子树高度复原 当子树高度复原时,其更高的祖先也必定平衡。 删除:同插入一样,也可以分为两种情况讨论,但不同的是,删除后经过单旋或双旋,原树高度不一定会复原,更高祖先仍可能失衡,这就是失衡传播现象,最坏需要做o(logn)次调整。 双旋: zigzig都在左侧,顺时针旋转 zagzag都在右侧,逆时针旋转 zigzag 右、左,双旋,之字形排列 zagzig 左、右 双旋实现:将三个节点(a,b,c)、四颗子树(A,B,C,D)看做单个元素做中序遍历,传入7个参数,最后返回一颗子树,该子树以b为根,左右孩子分别为a、c,a的孩子为A、B,c的孩子为C、D。此时树高最小。 双旋实现的启发:理论分析时使用的是形象的工具,实际操作时,往往有更暴力、性能更优的解,当然,这些解需要对理论的工具有更深的理解才能想到。
二、高级搜索树
1.伸展树:
伸展树期望解决的问题:
更快的访问。它依赖于这样一个现象:刚被访问过的数据,很有可能会很快的被再次访问;下一个访问的数据极有可能在刚访问的数据附近。这就是数据访问的局部性。伸展树的策略: 节点一旦被访问,随即调整至树根。自下而上,逐层单旋,直到被推到树根。
0 0
- 数据结构与算法小结(2)
- 数据结构与算法小结
- 数据结构与算法小结(1)
- 数据结构与算法----个人小结
- 【Java数据结构与算法04】 | 第2章--小结
- 数据结构小结(九)排序算法大杂烩
- [数据结构] 排序算法小结
- 数据结构与算法(2)
- 数据结构与算法2
- [数据结构与算法] 2,算法
- 软考——数据结构与算法小结
- 【Java数据结构与算法03】 | 第1章--小结
- 数据结构与算法(2)--贪心策略
- 数据结构,算法与应用(2)
- 算法与数据结构(2),Map
- 数据结构与算法(2)顺序表
- 数据结构与算法-动态规划(2)
- 数据结构小结 (三)栈与队列
- Codeforces 628E:Zbazi in Zeydabad 树状数组的奇妙用法
- jQuery图片上传前先在本地预览
- eclipse安装jad插件
- could not resolve host: github.com
- 常用的ADB命令
- 数据结构与算法小结(2)
- CentOS 6.3 编译安装 Nginx(含:管理脚本)
- URAL 1113(数学)
- 僵尸进程的产生和避免
- 本博客在2016/02/28被入侵了
- 关于getChildMeasureSpec()
- HashMap深度解析(一)
- Android中的线程
- hdu1561(树形dp)