问题描述
我正在尝试实现八字树。但是在splay()函数调用的left_rotate和right_rotate函数中发生了分段错误。我曾尝试调试,但一无所获。我在哪里做错了! 我认为存在某种逻辑错误。 这是我的代码:
splay_tree.h
#include"node.h"
template<class T>
class splay_tree{
private:
Node<T>* root=nullptr;
public:
splay_tree(){
root=nullptr;
}
//gethead
Node<T>* gethead(){
return this->root;
}
void left_rotate(Node<T>* node){
if(node==nullptr){return ;}
if(node->m_right!=nullptr){
Node<T>* temp= node->m_right;
node->m_right= temp->m_left;
if(temp->m_left){
temp->m_left->m_parent=node;
}
temp->m_parent=node->m_parent;
if(node->m_parent==nullptr){
this->root=temp;
}else if(node=node->m_parent->m_left){
node->m_parent->m_left=temp;
}else if(node=node->m_parent->m_right){
node->m_parent->m_right=temp;
}
temp->m_left=node;
node->m_parent=temp;
}
}
//right rotate
void right_rotate(Node<T>* node){
Node<T>* temp= node->m_left;
node->m_left=temp->m_right;
if(temp->m_right){
temp->m_right->m_parent=node;
}
temp->m_parent=node->m_parent;
if(node->m_parent==nullptr){
this->root=temp;
}else if(node==node->m_parent->m_left){
node->m_parent->m_left=temp;
}else{
node->m_parent->m_right=temp;
}
temp->m_right=node;
node->m_parent=temp;
}
//splaying the node
void splay(Node<T>* node){
while(node->m_parent){
if(node->m_parent->m_parent==nullptr){
if(node==node->m_parent->m_left){
right_rotate(node->m_parent);
}else if(node==node->m_parent->m_right){
left_rotate(node->m_parent);
}
}else if(node->m_parent->m_parent!=nullptr){
if(node==node->m_parent->m_left && node->m_parent==node->m_parent->m_parent->m_left){
right_rotate(node->m_parent->m_parent);
right_rotate(node->m_parent);
}else if(node==node->m_parent->m_right && node->m_parent==node->m_parent->m_parent->m_right){
left_rotate(node->m_parent->m_parent);
left_rotate(node->m_parent);
}else if(node==node->m_parent->m_right && node->m_parent==node->m_parent->m_parent->m_left){
right_rotate(node->m_parent);
left_rotate(node->m_parent);
}else{
left_rotate(node->m_parent);
right_rotate(node->m_parent);
}
}
}
}
void insert(T data){
insert(data,this->root);
}
Node<T>* insert(T data,Node<T>* node){
if(this->root==nullptr){
this->root= new Node<T>(data);
return this->root;
}else{Node<T>* curr_ptr=node;
while(node!=nullptr){
if(data<node->m_data){
if(node->m_left!=nullptr){
node->m_left=insert(data,node->m_left);
}else{
Node<T>* new_node = new Node<T>(data);
curr_ptr->m_left= new_node;
new_node->m_parent=curr_ptr;
splay(new_node);
}
}else if(data> node->m_data){
if(node->m_right!= nullptr){
node->m_right= insert(data,node->m_right);
}else{
Node<T>* new_node= new Node<T>(data);
curr_ptr->m_right= new_node;
new_node->m_parent=curr_ptr;
splay(new_node);
}
}
}
}
return node;
}
};
node.h
template<class T>
class Node{
public:
T m_data; // holds the key
Node<T>* m_parent; // pointer to the parent
Node<T>* m_left; // pointer to left child
Node<T>* m_right; // pointer to right child
Node(T data){
m_data=data;
m_left=nullptr ;
m_right=nullptr ;
m_parent=nullptr;
}
};
main.cpp
#include"splay_tree.h"
#include<iostream>
using namespace std;
int main(){
splay_tree<int> s1;
cout<<s1.gethead();
s1.insert(12);
s1.insert(89);
return 0;
}
解决方法
仔细查看后,您的操作肯定存在问题。 让我们用原理图分解left_rotate代码:
这是您进入旋转功能之前的样子
第一条指令Node<T>* temp = node->m_right
的结果是:
这本身并没有错,但是请注意,您的新节点临时节点缺少连接
最后,node->m_right = temp->m_left
在理论上会像这样:
如您所见,node->m_right
仍然有来自父母和孩子的传入连接,temp->m_left
会指向自己。这就是导致分割错误的原因。
您应该要纠正的错误是:
- 在将其分配给新节点之前,请确保已销毁与node-> m_right的所有连接。
- 不要忘记将连接添加到新的临时节点
好的,这就是我为您的代码找到的
您为旋转函数使用了错误的命名法,即您使用right_rotate时应在left_rotate处命名。
注意:这可能是因为您从某处获取代码,而从其他地方获取代码。我强烈建议您先自己尝试一下。
谈论命名Zig可以理解为向左还是向右,因此可能会造成混乱,这就是这里发生的情况!
对于答案部分,我已经更新了名称并改进了您的代码!
void left_rotate(Node<T>* node){
if(node==nullptr){return ;}
else{
Node<T>* temp= node->m_right;
node->m_right=temp->m_left;
if(temp->m_left){
temp->m_left->m_parent=node;
}
temp->m_parent=node->m_parent;
if(node->m_parent==nullptr){
this->root=temp;
}else if(node==node->m_parent->m_left){
node->m_parent->m_left=temp;
}else if(node== node->m_parent->m_right){
node->m_parent->m_right=temp;
}
temp->m_left=node;
node->m_parent=temp;
}
}
void right_rotate(Node<T>* node){
Node<T>* temp=node->m_left;
node->m_left=temp->m_right;
if(temp->m_right){
temp->m_right->m_parent=node;
}
temp->m_parent= node->m_parent;
if(node->m_parent==nullptr){
this->root=temp;
}else if(node==node->m_parent->m_left){
node->m_parent->m_left=temp;
}else if(node== node->m_parent->m_right){
node->m_parent->m_right=temp;
}
temp->m_right=node;
node->m_parent=temp;
}
//splay Function
void splay(Node<T>* node){
while(node->m_parent){
if(!node->m_parent->m_parent){
if(node==node->m_parent->m_left){//zig Rotation
right_rotate(node->m_parent);
}else if(node==node->m_parent->m_right){
left_rotate(node->m_parent);
}
}
else if(node==node->m_parent->m_left && node->m_parent==node->m_parent->m_parent->m_left){//Zig Zig
right_rotate(node->m_parent->m_parent);
right_rotate(node->m_parent);
}else if(node== node->m_parent->m_right && node->m_parent==node->m_parent->m_parent->m_right){//zag zag
left_rotate(node->m_parent->m_parent);
left_rotate(node->m_parent);
}else if(node==node->m_parent->m_left && node->m_parent== node->m_parent->m_parent->m_right){
right_rotate(node->m_parent);
left_rotate(node->m_parent);
}else if(node== node->m_parent->m_right && node->m_parent== node->m_parent->m_parent->m_left){
left_rotate(node->m_parent);
right_rotate(node->m_parent);
}
}
}
//Insert Function
void insert(T data){
Node<T>* new_node= new Node<T>(data);
Node<T>* y= nullptr;
Node<T>* x= this->root;
while (x!= nullptr){
y=x;
if(new_node->m_data<x->m_data){
x= x->m_left;
}
else{
x=x->m_right;
}
}
// y is a m_parent of x
new_node->m_parent=y;
if(y==nullptr){
this->root=new_node;
}else if(new_node->m_data<y->m_data){
y->m_left=new_node;
}else{
y->m_right=new_node;
}
splay(new_node);
}