ang*_*son 4 language-agnostic binary-tree wikipedia splay-tree
通过一些练习来磨练我的二叉树技能,我决定实现一个splay树,如维基百科:Splay树中所述.
我没有得到的一件事是关于插入的部分.
它说:
首先,我们在splay树中搜索x.如果x尚不存在,那么我们将找不到它,而是它的父节点y.其次,我们对y执行一个splay操作,它将y移动到splay树的根.第三,我们以适当的方式将新节点x作为root插入.以这种方式,y是新根x的左或右子.
我的问题是:与文章中的其他例子相比,上述文字似乎过于简洁,为什么会这样?似乎这里遗漏了一些问题.例如,在将y节点向上扩展到根之后,我不能盲目地用x替换root,并将x作为左或右子进行处理.
我们假设树中不存在该值.
我有这棵树:
10
/ \
5 15
/ \ \
1 6 20
Run Code Online (Sandbox Code Playgroud)
我想插入8.通过上面的描述,我将找到6节点,并且在普通的二叉树中,8将被添加为6节点的右子节点,但是在这里我首先必须展开6节点到root:
6
/ \
5 10
/ \
1 15
\
20
Run Code Online (Sandbox Code Playgroud)
那么这两个中的任何一个都是明显错误的:
8 8
\ /
6 6
/ \ / \
5 10 5 10
/ \ / \
1 15 1 15
\ \
20 20
6 is not greater than 8 10 is not less than 8
Run Code Online (Sandbox Code Playgroud)
在我看来,首先进行splaying,然后以root身份正确添加新值的唯一方法意味着我必须检查以下条件(将splayed节点添加为新root的左子节点):
但是,如果我要拆分我显示的节点,通过选择正确的子节点并将其作为新节点的右子节点附加,我会得到:
8
/ \
6 10
/ \
5 15
/ \
1 20
Run Code Online (Sandbox Code Playgroud)
但是,这个简单的改变是否会给我一棵正确的树?我很难想出一个例子,但这可能导致以下结果:
IE浏览器.一个树在展开后基本上看起来像这样,但在我更换根之前?
10
/ \
5 15
/ \
11 20
Run Code Online (Sandbox Code Playgroud)
我想添加13,这将使新树像这样:
13
/ \
10 15
/ / \
5 11 20 <-- 11, on the wrong side of 13
Run Code Online (Sandbox Code Playgroud)
或者这可能永远不会发生?
我的第二个问题是:如下所示重写操作不是更容易:
首先,我们在splay树中搜索x.如果x尚不存在,那么我们将找不到它,而是它的父节点y.然后我们将新节点添加为父节点的左子节点或右子节点.第三,我们在我们添加的节点上执行一个splay操作,它将新值移动到splay树的根.
强调我的表现我改变了什么.
我不明白你描述的问题是怎么发生的.如果要在此树中插入13,首先必须找到它的位置:
10
/ \
5 15
/ \
11 20
Run Code Online (Sandbox Code Playgroud)
从10开始,你从右边开始,从左边开始,从右边开始,从右边开始,然后从右边开始......然后你就没有更多元素了.如果13已经在树中,我们会发现它是11的右子.所以根据规则我们在11上执行一个splay操作,它将11移动到splay树的根:
11
/ \
10 15
/ \
5 20
Run Code Online (Sandbox Code Playgroud)
然后我们添加13作为新的根,11作为左子:
13
/ \
11 15
/ \
10 20
/
5
Run Code Online (Sandbox Code Playgroud)
现在没有问题.
首先,我们在splay树中搜索x.如果x尚不存在,那么我们将找不到它,而是它的父节点y.然后我们将新节点添加为父节点的左子节点或右子节点.第三,我们在我们添加的节点上执行一个splay操作,它将新值移动到splay树的根.
这听起来像它也会起作用,但如果我是你,我只是尝试实现维基百科中描述的版本,因为很多人已经测试了它,并且已经有很好的文档记录.