高手来看!!BST二分搜索树,不能正常删除

operatingtuzi 2008-12-19 07:26:20
在删除的时候遵循以下规则:
两个子树,有一个为空,则删除这个点,并让它指向不为空的那个子树
当两个都为空,直接删除
当两个都不为空,则让这个点的值等于他的右子树中的最小值。

// 6.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
using namespace std;


template<class T>
class BST;

template<class T>
class node
{
friend void Iterator( node<T>* r);
friend class BST<T>;
private:
T data;
node<T> *lp,*rp;
public:
node(){lp=rp=NULL;}
node(T d,node<T> *l=NULL,node<T> *r=NULL):data(d),lp(l),rp(r){}
T getdata(){return data;}
};

template<class T>
class BST
{
friend void Iterator( node<T>* r);
private:
node<T> *root;
int value;
node<T>* find(const T& x,node<T> *r)
{
if(r==NULL)return NULL;
if(x<r->data)
return find(x,r->lp);
else if(x>r->data)
return find(x,r->rp);
else return r;
}
void insert(const T& x,node<T> *&root)
{
if(root==NULL)
{
root=new node<T>(x);
cout<<"have inserted "<<x<<endl;
}
else if(x<root->data)
insert(x,root->lp);
else if(x>root->data)
insert(x,root->rp);
else ; // when the data equle to x,do nothing
}
node<T>*& min(node<T>* &r)
{
if(r->lp!=NULL)
return min(r->lp);
else if(r->rp!=NULL)
return min(r->rp);
else return r;
}
void remove(const T& x,node<T> * &root)
{
if(root==NULL)
{
cout<<"have not this data "<<x<<endl;
return;
}
else if(x<root->data)
remove(x,root->lp);
else if(x>root->data)
remove(x,root->rp);
else if(root->lp==NULL&&root->rp==NULL)
{
node<T> *q=root;
root=NULL;
delete q;
}
else if(root->lp==NULL)
{
node<T> *q=root;
root=root->rp;
delete q;
}
else if(root->rp==NULL)
{
node<T> *q=root;
root=root->lp;
delete q;
}
else // 这里有问题!!!!!!!!
{
node<T> *p=min(root->rp);
root->data=p->getdata();
remove(root->data,p);

}
}
public:
BST(int v)
{
root=NULL;
cout<<"input the element when "<<v<<" stop"<<endl;
T x;cin>>x;
while(x!=v)
{
insert(x,root);cin>>x;
}
}
node<T>* find(const T&x)
{
return find(x,root);
}

void insert(const T& x)
{
if(root==NULL)
{ root->data=x;cout<<"have inserted "<<x<<endl;}
else insert(x,root);
}
node<T> *& min()
{
if(root==NULL)
return NULL;
return min(root);
}

void remove(const T& x) //if lp is null and rp is null,remove it
{ //else if lp is null,replace it with its rp;
if(root==NULL) //if they are both not null,replace it with the smallest data of rp
{
cout<<"it is null"<<endl;return ;
}
remove(x,root);
}
node<T>* getroot()
{
return root;
}
};

template<class T>
void Iterator( node<T>* r)// 中序遍历
{
while(r!=NULL)
{
cout<<r->getdata()<<" ";
Iterator(r->lp);
Iterator(r->rp);
return;
}
}




int _tmain(int argc, _TCHAR* argv[])
{

BST<int> bst(100);
bst.insert(2);
bst.insert(3);
cout<<(bst.find(2))->getdata()<<endl;
cout<<"the tree is"<<endl;
Iterator( bst.getroot());
bst.remove(2);

bst.remove(7);
bst.remove(3); //这里会出错
cout<<"the tree is"<<endl;
Iterator( bst.getroot());
cin.get();
cin.get();

return 0;
}

运行时每输入一个数 按回车
输入100结束
测试用例如下:5 3 1 4 8 7 6 100
注意顺序不同 结果不同 所以请按本数据输入
删除有两个子树的情况出错了
请各位大虾帮忙!!!!
...全文
281 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
wsqshz 2008-12-24
  • 打赏
  • 举报
回复
node<T>*& min(node<T>* &r)
{
if(r->lp!=NULL)
return min(r->lp);
else if(r->rp!=NULL)
return min(r->rp);
else return r;
}
改为:
node<T>*& min(node<T>* &r)
{
if(r->lp!=NULL)
return min(r->lp);

return r;
}
最小值不可能在右子树
myoswin7 2008-12-24
  • 打赏
  • 举报
回复

改成这样试一试:

else {
node<T> *&p=min(root->rp);
root->data=p->getdata();
remove(root->data,p);

}
knate 2008-12-24
  • 打赏
  • 举报
回复
像你这个删除树结构的一个非子叶节点
一般是无序的。

在有序的树删除的多数是根。
否则保持有序需要牺牲较大性能,或者使用特别的存储形式或函数。
operatingtuzi 2008-12-23
  • 打赏
  • 举报
回复
继续顶!
期待有人指出来我的那个算法怎么改
operatingtuzi 2008-12-22
  • 打赏
  • 举报
回复
楼上真的很强悍!
连注释都写了!!

不过如果能把我调用min函数的那个地方,把我的min函数改过来的话就更好了!
elegant87 2008-12-21
  • 打赏
  • 举报
回复

/*关于二叉排序树的删除节点问题,难点在于当该节点的左右子树都不为空的时候!
左右子树都不为空,有两种方法。1.用该节点的直接先驱节点去替代,然后删除直接前驱节点
2.用该节点直接后继节点去替代,然后删除直接后继节点*/
//我用了第一种方法!你可以尝试用第二种方法试试!

#include <iostream>
using namespace std;


template<class T>
class BST;

template<class T>
class node
{
friend void Iterator( node<T>* r);
friend class BST<T>;
private:
T data;
node<T> *lp,*rp; //左右孩子指针
public:
node(){lp=rp=NULL;} //初始化
node(T d,node<T> *l=NULL,node<T> *r=NULL):data(d),lp(l),rp(r){}
T getdata(){return data;}
};

template<class T>
class BST
{
friend void Iterator( node<T>* r);
private:
node<T> *root; //树根指针
int value;
node<T>* find(const T& x,node<T> *r)
{
if(r==NULL)
return NULL;
if(x<r->data)
return find(x,r->lp);
else if(x>r->data)
return find(x,r->rp);
else return r;
}
void insert(const T& x,node<T> *&root)
{
if(root==NULL)
{
root=new node<T>(x);
cout<<"have inserted "<<x<<endl;
}
else if(x<root->data)
insert(x,root->lp);
else if(x>root->data)
insert(x,root->rp);
else
cout<<"the data has already inserted!"<<endl; // when the data equle to x,do nothing
}

node<T>*& min(node<T>* &r)
{
if(r->lp!=NULL)
return min(r->lp);
else if(r->rp!=NULL)
return min(r->rp);
else return r;
}

void remove(const T& x,node<T> * &root)
{
if(root==NULL)
{
cout<<"have not this data "<<x<<endl;
return;
}
else if(x<root->data) //在左子树中查找
remove(x,root->lp);
else if(x>root->data) //在右子树中查找
remove(x,root->rp);
//找到x值
else if(root->lp==NULL&&root->rp==NULL) //删除的节点为叶子节点
{
node<T> *q=root;
root=NULL;
delete q;
}
else if(root->lp==NULL) //删除的节点左子树为空
{
node<T> *q=root;
root=root->rp;
delete q;
}
else if(root->rp==NULL) //删除的节点右子树为空
{
node<T> *q=root;
root=root->lp;
delete q;
}
else // 这里有问题!!!!!!!! //左右子树都不为空,有两种方法。1.用该节点的直接先驱节点去替代,然后删除直接前驱节点!
//2.用该节点直接后继节点去替代,然后删除直接后继节点
{
node<T> *p,*s;
p=root;
s=root->lp ; //从左子树中找直接前驱
while(s->rp)
{
p=s;
s=s->rp;
}
root->data=s->data;
if(p!=root) //当root的左子树s的右子树不为空时
p->rp=s->lp;
else //当root的左子树s的右子树为空时
p->lp=s->lp;
delete s;

//node<T> *p=min(root->rp);
// root->data=p->getdata();
//remove(root->data,p);
}
}
public:
BST(int v)
{
root=NULL;
cout<<"input the element when "<<v<<" stop"<<endl;
T x;
cin>>x;
while(x!=v)
{
insert(x,root);
cin>>x;
}
}
node<T>* find(const T&x)
{
return find(x,root);
}

void insert(const T& x)
{
if(root==NULL)
{ root->data=x;cout<<"have inserted "<<x<<endl;}
else insert(x,root);
}
node<T> *& min()
{
if(root==NULL)
return NULL;
return min(root);
}

void remove(const T& x) //if lp is null and rp is null,remove it
{ //else if lp is null,replace it with its rp;
if(root==NULL) //if they are both not null,replace it with the smallest data of rp
{
cout<<"it is null"<<endl;return ;
}
remove(x,root);
}
node<T>* getroot()
{
return root;
}
};

template<class T>
void Iterator( node<T>* r)// 中序遍历
{
while(r!=NULL)
{
Iterator(r->lp);
cout<<r->getdata()<<" ";
Iterator(r->rp);
return;
}
}




int main()
{

BST<int> bst(100);
bst.insert(2);
bst.insert(3);
cout<<(bst.find(2))->getdata()<<endl;
cout<<"the tree is"<<endl;
Iterator( bst.getroot());
bst.remove(2);

bst.remove(7);
bst.remove(3);
cout<<"\nthe tree is"<<endl;
Iterator( bst.getroot());
cin.get();
cin.get();

return 0;
}
operatingtuzi 2008-12-20
  • 打赏
  • 举报
回复
继续期待。。

只要看标注出错的地方就行了
单步跟进去

不明白为什么指针后来有改过来了
operatingtuzi 2008-12-19
  • 打赏
  • 举报
回复
你们都运行了吗。。
单步执行过了
但是不明白为什么后来指针的值又改了 明明用的是引用。。

建议完整看过程序在发言。。
yshuise 2008-12-19
  • 打赏
  • 举报
回复
删除的时候判断指针是否为空。
wiowei 2008-12-19
  • 打赏
  • 举报
回复
有个东东叫debug。。单步一步一步走一圈还找不到错吗?

65,211

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧