首页 新闻 会员 周边 捐助

学习数据结构“伸展树”时遇到问题求大牛们不吝赐教!

0
[待解决问题]

  各位大牛们好!小弟我近日正在通过由本园“skywang12345”大牛整理的“数据结构与算法系列“文章学习数据结构,但学到“伸展树”这篇文章的时候遇到了困难,希望各位大牛能够不吝赐教。以下是该系列“伸展树”文章中的部分Java实现代码,分别是“伸展树”的“基本结构“实现和“节点旋转方法”的实现:

伸展树”基本结构

public class SplayTree<T extends Comparable<T>> {

    private SplayTreeNode<T> mRoot;    // 根结点

    public class SplayTreeNode<T extends Comparable<T>> {
        T key;                // 关键字(键值)
        SplayTreeNode<T> left;    // 左孩子
        SplayTreeNode<T> right;    // 右孩子

        public SplayTreeNode() {
            this.left = null;
            this.right = null;
        }

        public SplayTreeNode(T key, SplayTreeNode<T> left, SplayTreeNode<T> right) {
            this.key = key;
            this.left = left;
            this.right = right;
        }
    }

        
}

节点旋转方法

/*
* 旋转key对应的节点为根节点,并返回根节点。
*
* 注意:
* (a):伸展树中存在"键值为key的节点"。
* 将"键值为key的节点"旋转为根节点。
* (b):伸展树中不存在"键值为key的节点",并且key < tree.key。
* b-1 "键值为key的节点"的前驱节点存在的话,将"键值为key的节点"的前驱节点旋转为根节点。
* b-2 "键值为key的节点"的前驱节点存在的话,则意味着,key比树中任何键值都小,那么此时,将最小节点旋转为根节点。
* (c):伸展树中不存在"键值为key的节点",并且key > tree.key。
* c-1 "键值为key的节点"的后继节点存在的话,将"键值为key的节点"的后继节点旋转为根节点。
* c-2 "键值为key的节点"的后继节点不存在的话,则意味着,key比树中任何键值都大,那么此时,将最大节点旋转为根节点。
*/
private SplayTreeNode<T> splay(SplayTreeNode<T> tree, T key) {
if (tree == null)
return tree;

SplayTreeNode<T> N = new SplayTreeNode<T>();
SplayTreeNode<T> l = N;
SplayTreeNode<T> r = N;
SplayTreeNode<T> c;

for (;;) {

int cmp = key.compareTo(tree.key);
if (cmp < 0) {

if (tree.left == null)
break;

if (key.compareTo(tree.left.key) < 0) {
c = tree.left; /* rotate right */
tree.left = c.right;
c.right = tree;
tree = c;
if (tree.left == null)
break;
}
r.left = tree; /* link right */
r = tree;
tree = tree.left;
} else if (cmp > 0) {

if (tree.right == null)
break;

if (key.compareTo(tree.right.key) > 0) {
c = tree.right; /* rotate left */
tree.right = c.left;
c.left = tree;
tree = c;
if (tree.right == null)
break;
}

l.right = tree; /* link left */
l = tree;
tree = tree.right;
} else {
break;
}
}

l.right = tree.left; /* assemble */
r.left = tree.right;
tree.left = N.right;
tree.right = N.left;

return tree;
}

public void splay(T key) {
mRoot = splay(mRoot, key);
}

 

 小弟我的困难由如下几项:

  一,节点旋转方法文本注释中的b项和c项小弟我不是很理解,恳求大牛们为小弟我指点迷津。

  二,由于节点旋转方法实现内容有些复杂,所以小弟我采用了debug调试来试图理解,但在代码一步步执行观察方法中变量值的变化的时候小弟我遇到了理解上困难,下面是两种debug调试时的图:

图一

 

图二

小弟我想不通为什么变量l和变量r同样都引用了N值,为什么r.left值的变化能引起另外两个l和N值相应的left的变化,而l.right值的变化只能引起N值的right值的变化却引不起r值的right?再次恳请大牛们不吝赐教!

问题补充:

为大牛们奉上这篇“伸展树”文章的原地址:

http://www.cnblogs.com/skywang12345/p/3604286.html

wszwhh的主页 wszwhh | 初学一级 | 园豆:166
提问于:2018-04-19 10:40
< >
分享
所有回答(1)
0

没有真正理解伸展树呀。

你的第一个问题,b和c说的很容易让人产生歧义,其实意思就是将key与根节点root的key进行比较,

1)key<root.key说明key对应的节点在左子树上,然后将key与root.left.key进行比较来确定是双旋转还是单旋转

2)key>root.key同理

3)key==root.key时说明你已经找到需要找到的节点了。

 

伸展树的伸展操作就是寻找指定节点,然后将指定节点放到根节点上。

母翟龙 | 园豆:204 (菜鸟二级) | 2018-06-03 23:32
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册