#include <iostream>
using namespace std;
template<typename T>
class SplayTree{
//自顶向下伸展树是查找树,即左孩子小于根节点,右孩子大于根节点,但不维持平衡,摊还时间复杂度是O(logN)
//基本思想是考虑到局部性原理,现在访问过的节点以后可能还会经常访问,因此访问过一个节点后就把它放到根上
//并且把访问路径上的大部分节点的深度大致减少一半,通过一次伸展降低以后继续操作的开支
private:
struct SplayTreeNode{
T data;
SplayTreeNode* left;
SplayTreeNode* right;
SplayTreeNode():left(nullptr),right(nullptr){};
SplayTreeNode(T v,SplayTreeNode* l,SplayTreeNode* r):data(v),left(l),right(r){};
};
SplayTreeNode* root; //根节点
void inOrderTraversal(SplayTreeNode* node){
if (!node) return;
inOrderTraversal(node->left);
cout << node->data << ' ';
inOrderTraversal(node->right);
}
SplayTreeNode* find(SplayTreeNode* t,T x){
//在t里找x
while (!t || t->data!=x){
if (x<t->data) t=t->left;
else t=t->right;
}
return t;
}
SplayTreeNode* findMax(SplayTreeNode* t){
if (!t) return t;
while (t->right) t=t->right;
return t;
}
SplayTreeNode* splay(SplayTreeNode* tree,T x){
//伸展
SplayTreeNode N, *l, *r, *c;
if (!tree) return nullptr;
N.left = N.right = nullptr;
l = r = &N;
for (;;){
if (x < tree->data){
if (!tree->left) break;
if (x < tree->left->data){
//右旋
c = tree->left;
tree->left = c->right;
c->right = tree;
tree = c;
if (!tree->left) break;
}
//链接
r->left = tree;
r = tree;
tree = tree->left;
}
else if (x > tree->data){
if (!tree->right) break;
if (x > tree->right->data){
//左旋
c = tree->right;
tree->right = c->left;
c->left = tree;
tree = c;
if (!tree->right) break;
}
//链接
l->right = tree;
l = tree;
tree = tree->right;
}
else break;
}
//组合
l->right = tree->left;
r->left = tree->right;
tree->left = N.right;
tree->right = N.left;
return tree;
}
SplayTreeNode* insert(SplayTreeNode* &tree, SplayTreeNode* z){
//将z插入tree中,返回根节点
SplayTreeNode *y = nullptr;
SplayTreeNode *x = tree;
// 查找z的插入位置
while (x){
y = x;
if (z->data < x->data) x = x->left;
else if (z->data > x->data) x = x->right;
else{
cout << "不允许插入相同节点(" << z->data << ")!" << endl;
delete z;
return tree;
}
}
if (!y) tree = z;
else if (z->data < y->data) y->left = z;
else y->right = z;
return tree;
}
SplayTreeNode* remove(SplayTreeNode* &tree, T key){
SplayTreeNode *x;
if (!tree) return nullptr;
// 查找键值为key的节点,找不到的话直接返回。
if (!find(tree, key)) return tree;
// 将key对应的节点旋转为根节点。
tree = splay(tree, key);
if (tree->left){
// 将"tree的前驱节点"旋转为根节点
x = splay(tree->left, key);
// 移除tree节点
x->right = tree->right;
}
else x = tree->right;
delete tree;
return x;
}
public:
SplayTree():root(nullptr){};
void inOrderTraversal(){inOrderTraversal(root);}
SplayTreeNode* find(T x){return find(root,x);}
T findMax(){
SplayTreeNode* t=findMax(root);
if (t) return t->data;
return T(-1);
}
void splay(T x){root=splay(root,x);} //将x旋转到根节点
void insert(T x){
SplayTreeNode* z=new SplayTreeNode(x,nullptr,nullptr);
root=insert(root,z);
root=splay(root,x);
}
void remove(T x){root=remove(root,x);}
};
int main(){
SplayTree<int>* t=new SplayTree<int>();
for (int i=0;i<10;i++) t->insert(i);
//t->inOrderTraversal();
cout << t->findMax();
cout << endl;
t->remove(9);
cout << t->findMax();
cout << endl;
t->insert(23);
cout << t->findMax();
cout << endl;
t->remove(2);
t->midOrderTraversal();
cout << endl;
return 0;
}
数据结构与算法分析:伸展树
于 2022-10-02 18:52:31 首次发布