JAVA之伸展树
来源:互联网 发布:食堂刷卡机数据采集 编辑:程序博客网 时间:2024/06/06 05:07
- 伸展树与二叉平衡查找树
AVL树(带有平衡条件的树)查找的时候最坏的情形为0(N)并不坏,只要它不经常发生就可以。任何一次访问,即使花费0(N),任然可能非常快。具有最坏运行时间0(N)但保证对任意M次连续操作最多花费O(MlogN)运行时间确实让人满意了。
伸展树和其它树的区别就是没访问一个节点的时候,那个节点就会成为根节点,这样下次访问的时候时间为0(1)并且与二叉平衡查找树比少了高度的属性和判断平衡信息,因此从某种程度上简化代码。
在伸展树中最主要的一部分就是伸展,分为两种情况第一种是之字形(zig-zag)情形,第二种就是一字形(zig-zig)
package tree;/* * 伸展树:他保证从空树开始连续M次对树的操作最多花费0(MlogN)时间 */public class STree<AnyType extends Comparable<? super AnyType>>{ private Node root; private class Node{ public Node left;//左孩子 public Node right;//右孩子 public Node parent;//父亲节点 public AnyType x;//data数据 public Node(AnyType x){ this.x = x; parent = null; left = null; right = null; } } public STree(){ root = null; } //查找 public AnyType find(AnyType key){ root = find(root, key); if(root == null || root.x.compareTo(key) != 0) return null; return root.x; } private Node find(Node p, AnyType key){ if(p == null || key == null) return null; Node prep = null; while(p != null){ prep = p; int cmp = key.compareTo(p.x); if(cmp < 0) p = p.left; else if(cmp > 0) p = p.right; else break; } root = splay(prep); return root; } //插入 public void insert(AnyType data){ if(data == null) return; if(root == null){ root = new Node(data); return; } Node t = find(root, data); int cmp = data.compareTo(t.x); if(cmp == 0){//更新value root.x = data; return; } root = new Node(data); //先把T分为左右子树,再合并 if(cmp < 0){//插入新根,以t->lchild和t为左/右孩子 Node x = t.left; root.left = x; root.right = t; t.parent = root; if(x != null){ x.parent = root; t.left = null; } }else if(cmp > 0){ Node x = t.right; root.left = t; root.right = x; t.parent = root; if(x != null){ x.parent = root; t.right = null; } } } //删除 public void delect(AnyType key){ if(key == null) return; Node t = find(root, key); if(t == null || key.compareTo(t.x) != 0) return; if(t.right == null){//右子树为空 root = root.left; root.parent = null; return; } //右子数不空 //1.删除T节点, 得到子树tl, tr Node tl = t.left, tr = t.right; tr.parent = null; //2.将右子树最小节点min伸展至右子树树根,min一定没有左子节点 Node min = min(tr); //3.将tl作为左子树链接到min上 min.left = tl; if(tl != null) tl.parent = min; root = min; } public AnyType min(){ if(root == null) return null; root = min(root); return root.x; } private Node min(Node x){ if(x == null) return null; while(x.left != null) x = x.left; x = splay(x); return x; } public AnyType max(){ if(root == null) return null; root = max(root); return root.x; } private Node max(Node x){ if(x == null) return null; while(x.right != null) x = x.right; x = splay(x); return x; } private Node splay(Node v){//v是找到的节点 if(v == null) return null; Node p, g; //v的父亲与祖父 //自上而下,反复对v做双层伸展 while((p = v.parent) != null && (g = p.parent) != null){ Node gg = g.parent;//(great-grand parent)为父 if(isLChild(v)){ if(isLChild(p)){//zig-zig(g)先g结点右旋,zig(p)在p右旋 attachAsLChild(g, p.right); attachAsRChild(p, g); attachAsLChild(p, v.right); attachAsRChild(v, p); }else{//zig-zag(p)先p右旋,再g左旋zag(g) attachAsLChild(p, v.right); attachAsRChild(v, p); attachAsRChild(g, v.left); attachAsLChild(v, g); } }else{ if(isRChild(p)){//zag-zag,zag(g)先g结点左旋,zig(p)再p左旋 attachAsRChild(g, p.left); attachAsLChild(p.left, g); attachAsRChild(p, v.left); attachAsLChild(v, p); }else{//zag-zig,先p左旋,zag(p),再g右旋zig(g) attachAsRChild(p, v.left); attachAsLChild(v, p); attachAsLChild(g, v.right); attachAsRChild(v, g); } } //若v原先的曾祖父gg不存在, 则v现在应为树根 if(gg == null) v.parent = null; else{//否则,gg此后应该以v作为左或右孩子 if(gg.left == g) attachAsLChild(gg, v); else attachAsRChild(gg, v); } } //双层伸展结束时,必有g == null, 但p可能非空 //若p果真非空,则额外在做一次单旋 if(p != null && p == v.parent){ if(isLChild(v)){//zig attachAsRChild(p, v.right); attachAsRChild(v, p); }else{//zag attachAsRChild(p, v.left); attachAsLChild(v, p); } } v.parent = null; return v; } //判断n是否是父节点的左孩子 private boolean isLChild(Node n){ Node p = n.parent; return p.left == n; } //判断n是否是父节点的右孩子 private boolean isRChild(Node n){ Node p = n.parent; return p.right == n; } //在节点p与rc(可能为空)之间建立父(左)子关系 private void attachAsLChild(Node parent, Node lchild){ parent.left = lchild; if(lchild != null) lchild.parent = parent; } //在节点p与rc(可能为空)之间建立父(右)子关系 private void attachAsRChild(Node parent, Node rchild){ parent.right = rchild; if(rchild != null) rchild.parent = parent; } public void prearder(){ prearder(root); System.out.println("前序遍历"); System.out.println(); } private void prearder(Node p){ if(p == null) return; System.out.print(p.x+" "); prearder(p.left); prearder(p.right); } //测试 public static void main(String[] args){ STree<Integer> st = new STree<Integer>(); for(int i=0; i<10; i++) st.insert(i); st.find(5); st.prearder(); }}
0 0
- JAVA之伸展树
- 伸展树 之 Java的实现
- 数据结构之伸展树
- 数据结构之伸展树
- 数据结构之伸展树
- 数据结构之伸展树
- 伸展树--Java实现
- 伸展树:双层伸展
- 数据结构实现之Splay伸展树
- 伸展树splay之求区间极值
- 用Java泛化写的伸展树
- Java基础 - 伸展树(SplayTree)
- 伸展树
- 伸展树
- 伸展树
- 伸展树
- 伸展树
- 伸展树
- HDU1409-Is It a Number
- Spring整合myBatis时无法读取placeholder的问题解决
- Android JNI基础
- react按需加载
- 手游资源热更新策略探讨
- JAVA之伸展树
- 通过Spring Boot三分钟创建Spring Web项目
- 数据结构初探(一)「基础知识」
- html之列表标签
- 数据结构和算法总结
- lambda
- 每天一题LeetCode[第五天]
- 使用highcharts来建立多轴时间序列图
- yacc&lex-Chapter1