单旋转
一字形旋转
SplayTree SingleRotateWithLeft(SplayTree Sp) // 一字形旋转(左)类似AVL单左旋
{
SplayNode* X = Sp;
SplayNode* Y = Sp->left; // 用X和Y标记树的根节点及左孩子
X->left = Y->right; // X的左孩子赋值为Y的右孩子
Y->right = X;
return Y; // 返回Y
}
之字形旋转
之字形旋转简化
SplayTree Splay(SplayTree Sp, ElementType key) // 自顶向下的展开过程
{
SplayTree L = Initialize(); // 借助L和R实现展开过程
SplayTree R = Initialize();
SplayNode* LeftTreeMax = L; // 定义LeftTreeMax指针指向左子树的最大关键字所在的节点
SplayNode* RightTreeMin = R; // 定义RightTreeMin指针指向右子树的最小关键字所在的节点
while (Sp && key != Sp->value) // 自顶向下依次迭代伸展
{
if (key < Sp->value)
{
if (Sp->left && key < Sp->left->value) // 一字形旋转(左)的条件
Sp = SingleRotateWithLeft(Sp);
if (!Sp->left)
break;
// 连接到R中,当不满足一字形旋转条件时,下面两句是直接执行单旋转
RightTreeMin->left = Sp;
RightTreeMin = Sp;
Sp = Sp->left; // 迭代往左
}
else
{
if (Sp->right && key > Sp->right->value) // 一字形旋转(右)的条件
Sp = SingleRotateWithRight(Sp);
// 连接到L中,当不满足一字形旋转时,下面两句是直接执行单旋转
if (!Sp->right)
break;
LeftTreeMax->right= Sp;
LeftTreeMax = Sp;
Sp = Sp->right; // 迭代往右
}
}
// 重构树
LeftTreeMax->right = Sp->left;
RightTreeMin->left = Sp->right;
Sp->left = L->right;
Sp->right = R->left;
return Sp;
}
#include<iostream>
using namespace std;
#define ElementType int
typedef struct TreeNode { // 定义树节点结构
ElementType value; // 关键字值
TreeNode* left; // 左孩子
TreeNode* right; // 右孩子
}SplayNode, *SplayTree;
static SplayNode* NullNode = nullptr; // 定义一个空节点静态局部变量,初始化为空指针
SplayTree Initialize()
{
SplayTree Sp = new SplayNode;
Sp->left = nullptr;
Sp->right = nullptr;
return Sp;
}
SplayTree SingleRotateWithLeft(SplayTree Sp) // 一字形旋转(左)类似AVL单左旋
{
SplayNode* X = Sp;
SplayNode* Y = Sp->left; // 用X和Y标记树的根节点及左孩子
X->left = Y->right; // X的左孩子赋值为Y的右孩子
Y->right = X;
return Y; // 返回Y
}
SplayTree SingleRotateWithRight(SplayTree Sp) // 一字形旋转(右)类似AVL单右旋
{
SplayNode* X = Sp;
SplayNode* Y = Sp->right; // 用X和Y标记树的根节点及右孩子
X->right = Y->left; // X的右孩子赋值为Y的左孩子
Y->left = X;
return Y; // 返回Y
}
SplayTree Splay(SplayTree Sp, ElementType key) // 自顶向下的展开过程
{
SplayTree L = Initialize(); // 借助L和R实现展开过程
SplayTree R = Initialize();
SplayNode* LeftTreeMax = L; // 定义LeftTreeMax指针指向左子树的最大关键字所在的节点
SplayNode* RightTreeMin = R; // 定义RightTreeMin指针指向右子树的最小关键字所在的节点
while (Sp && key != Sp->value) // 自顶向下依次迭代伸展
{
if (key < Sp->value)
{
if (Sp->left && key < Sp->left->value) // 一字形旋转(左)的条件
Sp = SingleRotateWithLeft(Sp);
if (!Sp->left)
break;
// 连接到R中,当不满足一字形旋转条件时,下面两句是直接执行单旋转
RightTreeMin->left = Sp;
RightTreeMin = Sp;
Sp = Sp->left; // 迭代往左
}
else
{
if (Sp->right && key > Sp->right->value) // 一字形旋转(右)的条件
Sp = SingleRotateWithRight(Sp);
// 连接到L中,当不满足一字形旋转时,下面两句是直接执行单旋转
if (!Sp->right)
break;
LeftTreeMax->right= Sp;
LeftTreeMax = Sp;
Sp = Sp->right; // 迭代往右
}
}
// 重构树
LeftTreeMax->right = Sp->left;
RightTreeMin->left = Sp->right;
Sp->left = L->right;
Sp->right = R->left;
return Sp;
}
SplayTree Insert(SplayTree Sp, ElementType key) // 向伸展树中插入关键字key
{
static SplayNode* NewNode = nullptr;
if (!NewNode)
{
NewNode = new SplayNode;
}
NewNode->value = key;
if (!Sp)
{
Sp = Initialize();
Sp->value = key;
}
else
{
Sp = Splay(Sp, key); // 展开
if (key < Sp->value)
{
NewNode->left = Sp->left;
NewNode->right = Sp;
Sp->left = nullptr;
Sp = NewNode;
}
else if (key > Sp->value)
{
NewNode->right = Sp->right;
NewNode->left = Sp;
Sp->right = nullptr;
Sp = NewNode;
}
else
return Sp; // 关键字已经在树中
}
NewNode = nullptr;
return Sp;
}
void Preorder(const SplayTree &Sp) // 先序遍历树
{
if (Sp != nullptr)
{
cout << Sp->value << " ";
Preorder(Sp->left);
Preorder(Sp->right);
}
}
void Find(SplayTree &Sp, ElementType key) // 在伸展树中查找关键字key
{
if (Sp == nullptr)
{
cout << "Empty Tree\n";
return;
}
else
{
Sp = Splay(Sp, key); // 展开
if (key == Sp->value)
{
cout << Sp->value<<" Has been Found!" << endl;
}
else
{
cout << "The number is not in the tree.\n";
}
}
}
SplayTree Delete(SplayTree Sp, ElementType key)
{
SplayTree NewTree = Initialize();
if (Sp != nullptr)
{
Sp = Splay(Sp, key); // 按关键字key展开树,使带key节点成为新的根节点
if (key == Sp->value)
{
if (Sp->left == nullptr) // 如果调整后的伸展树左孩子为空,
NewTree = Sp->right; // 则newTree为其右孩子
else
{
//NewTree = Sp->left; // 新树的根节点指向旧树的左孩子
NewTree = Splay(Sp->left, key); // 重新按照key调整新树
NewTree->right = Sp->right; // 新树的右孩子指向旧树的右孩子
}
delete Sp;
}
}
return NewTree;
}
int main()
{
int A[] = { 16,13,18,15,24,20,30,5,25,12,2 };
SplayTree SpTree = nullptr;
for (int i = 0;i < sizeof(A) / sizeof(int);i++)
{
SpTree = Insert(SpTree, A[i]);
}
cout << "The preorder print of the Tree is: \n";
Preorder(SpTree);
int number;
cout << "\nInput a number to find:\n";
cin >> number;
Find(SpTree, number);
cout << "The preorder print of the Tree is: \n";
Preorder(SpTree);
cout << "\nDelete the number " << number << " from the tree.\n";
SpTree = Delete(SpTree, number);
cout << "The preorder print of the Tree is: \n";
Preorder(SpTree);
cout << endl;
system("pause");
return 0;
}
运行结果
The preorder print of the Tree is:
2 5 12 13 25 24 18 15 16 20 30
Input a number to find:
16
16 Has been Found!
The preorder print of the Tree is:
16 5 2 13 12 15 24 18 20 25 30
Delete the number 16 from the tree.
The preorder print of the Tree is:
15 13 5 2 12 24 18 20 25 30
请按任意键继续. . .
Mark Allen Weiss: 数据结构与算法分析