昨天加今天,一直写不好关于二叉搜索树的代码,主要思想没有理解透彻,终于,今天晚上把他们做了出来,也多了许多感悟,具体见代码。
/*根据升序数组构造平衡二叉搜索树*/
#include <stdio.h>
#include <stdlib.h>
typedef struct tree_node_s {
char data;
struct tree_node_s *lchild;
struct tree_node_s *rchild;
}tree_node_t, *Tree;
//无序数组建立有序二叉树
Tree OrderTree(int *a,int length)
{
Tree insertTree(Tree &b,int x);
Tree t=NULL;
t=(Tree)malloc(sizeof(tree_node_t));
t->data=*a;
t->lchild=NULL;
t->rchild=NULL;
for(int i=1;i<length;i++)
{
t=insertTree(t,a[i]);
}
return t;
}
//升序建立二叉树
Tree BinNodeBuildTree(int *a,int start,int end)
{
int mid =(end+start)/2;
Tree t=NULL;
int b=a[mid];
if(start>end)
return t;
t=(Tree)malloc(sizeof(tree_node_t));
t->lchild=NULL;
t->rchild=NULL;
t->data=b;
t->lchild=BinNodeBuildTree(a,start,mid-1);
t->rchild=BinNodeBuildTree(a,mid+1,end);
return t;
}
//先序遍历
void PreOrder(Tree b)
{
if(b!=NULL)
{
printf("\t%d",b->data);
PreOrder(b->lchild);
PreOrder(b->rchild);
}
}
//中序遍历
void InOrder(Tree b)
{
if(b!=NULL)
{
InOrder(b->lchild);
printf("\t%d",b->data);
InOrder(b->rchild);
}
}
//查找节点
Tree searchTree(Tree &b,int x)
{
bool solve=false;
Tree p;
p=b;
while(p && !solve) //最后,1.p找到,!solve=false,(p && !solve)=0,跳出循环。
// 2.p未找到,p=NULL,!solve=true,(p && !solve)=0,也跳出循环。
{
if(x==p->data)
{
printf("已找到%d\n",x);
solve=true;
return p;
}else if(x<p->data){
p=p->lchild;
}else{
p=p->rchild;
}
}
if(p==NULL)
{
printf("没有找到\n");
}
return b;
}
//插入节点
Tree insertTree(Tree &b,int x)
{
Tree p;
p=(Tree)malloc(sizeof(tree_node_t));
p->data=x;
p->lchild=NULL;
p->rchild=NULL;
if(b==NULL)
{
return p;
}
if(p->data < b->data)
{
b->lchild=insertTree(b->lchild,x);
}else{
b->rchild=insertTree(b->rchild,x);
}
return b;
}
//非递归方法插入节点
void insertTree2(Tree &b,int x)
{
Tree p;
p=(Tree)malloc(sizeof(tree_node_t));
p->data=x;
p->lchild=NULL;
p->rchild=NULL;
while(b->lchild!=NULL && b->rchild!=NULL)
{
if(p->data<b->data)
{
b=b->lchild;
if(b==NULL)
{
b=p;
}
}else{
b=b->rchild;
if(b==NULL)
{
b=p;
}
}
}
}
//删除节点
void deleteTree(Tree &b,int x)
{
Tree p,q;//p为所找的节点,q为所找节点的父节点
p=b;
while(p!=NULL)
{
if(x==p->data)
{
break;
}else if(x>p->data){
q=p;
p=p->rchild;
}else{
q=p;
p=p->lchild;
}
}
if(p==NULL)
{
printf("无此节点:%d",x);
}
//若p是叶子节点
if(p->lchild==NULL&&p->rchild==NULL)
{
if(p==b)//p是根
b=NULL;
else if(q->lchild==p)
{
q->lchild=NULL;
p=NULL;
}else{
q->rchild=NULL;
p=NULL;
}
free(p);
}
//若p为单支节点
else if(p->rchild==NULL&&p->lchild!=NULL) //p的右子树为空
{
if(p==b)
{
if(p->lchild==NULL)
{
b=p->rchild;
}else{
b=p->lchild;
}
}
else if(q->lchild==p)
{
q->lchild=p->lchild;
}
else
{
q->rchild=p->lchild;
}
free(p);
}
else if(p->rchild!=NULL&&p->lchild==NULL) //p的左子树为空
{
if(p==b)
{
if(p->lchild==NULL)
{
b=p->rchild;
}else{
b=p->lchild;
}
}
else if(q->lchild==p)
{
q->lchild=p->rchild;
}
else
{
q->rchild=p->rchild;
}
free(p);
}
//p的左右子树均不为空
//如果一个结点有右孩子,则该结点的后继,至多有一个子女,而且是右孩子。
//因为假如该结点的后继有左孩子和右孩子,那么其左孩子的值肯定是介于该结点和其后继之间的,
//那么按照二叉查找树的性质,这个左孩子就应该是该结点的后继,所以,这与原先的后继相互矛盾.
else //(p->lchild!=NULL&&p->rchild!=NULL)
{
//找到P的后继节点,即p的右子树的最小值,即右子树的左子书的最后一个值
Tree n,m;//n 为p的后继,m 为n的父节点
n=p->rchild;
while(n->lchild)
{
m=n;
n=n->lchild;
}
p->data=n->data;
m->lchild=n->rchild;
}
}
int main ()
{
Tree p=NULL;
Tree q=NULL;
int a[12]={15,5,16,3,12,20,10,13,18,23,6,7};
int b[5]={1,2,3,6,5};
p=OrderTree(a,12);
InOrder(p);
printf("\n");
deleteTree(p,5);
InOrder(p);
printf("\n");
/* p=BinNodeBuildTree(a,0,4);
q=BinNodeBuildTree(a,0,4);
PreOrder(p);
printf("\n");
insertTree(p,4);
PreOrder(p);
printf("\n");
insertTree2(q,4);
PreOrder(p);
printf("\n");*/
return 0;
}另外,还发现了一个问题,废了我很长时间,代码没有错误,但是就是无法执行到底,发现是用了太多的if,不知道用太多的if还会出问题?我把他们改成了else If,就可以好好执行了,
本文通过具体的代码示例,详细介绍了如何使用C语言实现二叉搜索树的各种操作,包括构造平衡二叉搜索树、先序与中序遍历、节点的查找、插入与删除等,并分享了一些在实践中遇到的问题及解决方法。
667

被折叠的 条评论
为什么被折叠?



