A recursive implementation:
1. After reaching 4 you've the item to be looked up returning it to the previous level.
2. When returning to 3 you'll detect the returned 4 as your right node - but because 3 isn't the root node, there's nothing else to do than returning node 4 to node 2.
3. At node 2 you'll detect node 4 as your rightmost grandchild. Now you've to rotate left two times: At first at node 2 and than at the new top node of the resulting subtree namely node 3. You'll get 4-3-2 where 4 is the root of this subtree. Now you'll return this subtree to node 1.
4. Node 1 just points to node 2 as its right node. Because we don't detect the returned subtrees top level node 4 as our right child nor grandchild, we've to replace our right child pointer by this subtree. Then we'll return to 0 with our right subtree (with 4 as top level node).
At this moment our tree should look like:
5. At level 0 we'll detect the returned top level node, namely 4, as our right most grandchild. So we've to do two more rotation to the left like before. That's it!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
template <typename ItemType>
class BstNode
{
private:
typedef BstNode<ItemType> BstItemNode;
private:
ItemType _data;
BstItemNode *_left, *_right; // May be left undefined before Dest
private:
BstItemNode &rotateLeft();
BstItemNode &rotateRight();
BstItemNode *splay(const ItemType &val, bool isRootLevel);
//...
} /* BstNode */;
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
|
template <typename ItemType>
BstNode<ItemType> *BstNode<ItemType>::splay(const ItemType &val, bool isRootLevel)
{
BstItemNode *nodeFound;
if (val < _data)
{
if (_left == nullptr)
{
nodeFound = this;
}
else
{
nodeFound = _left->splay(val, false);
if (nodeFound != _left)
// zig - ...
{
if (nodeFound == _left->_left)
// ... - zig
{
rotateRight().rotateRight();
}
else if (nodeFound == _left->_right)
// ... - zag
{
_left = &_left->rotateLeft();
rotateRight();
}
else
{
_left = nodeFound;
}
}
if (nodeFound == _left)
// zig
{
if (isRootLevel)
{
rotateRight();
}
}
}
}
else if (_data < val)
{
if (_right == nullptr)
{
nodeFound = this;
}
else
{
nodeFound = _right->splay(val, false);
if (nodeFound != _right)
// zig - ...
{
if (nodeFound == _right->_right)
// ... - zig
{
rotateLeft().rotateLeft();
}
else if (nodeFound == _right->_left)
// ... - zag
{
_right = &_right->rotateRight();
rotateLeft();
}
else
{
_right = nodeFound;
}
}
if (nodeFound == _right)
// zig
{
if (isRootLevel)
{
rotateLeft();
}
}
}
}
else // (_data == val)
{
nodeFound = this;
}
assert(nodeFound != nullptr);
return nodeFound;
} /* splay() */
|