二叉排序树 插入 删除 遍历
这两天要弄数据结构考试,就在写二叉排序树
二叉排序树总共三个操作:插入,查找,删除,遍历;
先提醒对于插入,删除等要改变这棵树的操作都要用二维指针,否则不能改变,而遍历( 打印 ),查找( 这里的查找因为要为删除服务,所以用了二维指针,其实纯粹的查找是不需要的 )不需改变他的值,所以不用二维指针
插入:小的往左边放,大的往右边放,相等的直接不要,然后递归处理就可以了。
查找:如果查找的值等于当前节点,则返回当前节点,若查找的值比当前节点小则在当前节点的左子树中去找,若比当前节点大,则在当前右子树中去找,若差找不成功,返回NULL;
删除:这个是最令我头痛的,开始按数据结构上的来,一直改不对,就一直在找事不是指针的问题,改了一晚上没结果,最后看到一份文档把删除节点的思想看懂了才写出来的。大意如下:
总共分为两种情况,假设要删除的节点p,一种是有左子树,另一种是没左子树(包括p没孩子的那一种);当有左子树时,就在p的左子树中找到最右边的那一个(即p左子树中最大的那一个)r,用r的值取代p的值,这样就把p原来的值给覆盖了,那么p也就不存在了,这样还多出一个节点r,怎么办呢,当然是删除啊,但是r可能还有左子树,若r还有左子树就用r的左子树取代r的位子就行了。另一种情况没有左子树那么就用p的右子树取代他的位置,然后再删掉他原来的节点就可以了( p没孩子的情况也适用这种情况 );
遍历:直接一个中序遍历就可以了;
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
typedef struct Node
{
int data;
struct Node *lc,*rc;
}node,*Link;
void insert( Link *L,int n )
{
if( *L == NULL )
{
( *L ) = new node;//若找到插入位置,则新申请节点
( *L ) -> lc = ( *L ) -> rc = NULL;
( *L ) -> data = n;
}
else
{
if( n == ( *L ) -> data )//若n与当前节点的值相等,则不需插入了
return ;
else if( n < ( *L ) -> data )//若n比当前节点的值小,则往当前节点的左子树插
insert( &( *L ) -> lc,n );
else//若n比当前节点的值大,则往当前节点的右子树插
insert( &( *L ) -> rc,n );
}
}
Link *Search( Link *L,int x )
{
Link p;
if( *L )
{
if( ( *L ) -> data == x )//若找到节点,则返回当前节点
return L;
if( x < ( *L ) -> data )//若x比当前节点的值小,则在当前节点的左子树中去找
return Search( &( *L ) -> lc, x );
else//若x比当前节点的值大,则在当前节点的右子树中去找
return Search( &( *L ) -> rc, x );
}
return NULL;
}
void Delete( Link *p )
{
if( ( *p ) -> lc )//若有左子树
{
Link pre = ( *p ) -> lc;
Link r = ( *p ) -> lc;
while( r -> rc )//去查找左子树中最右边的节点
pre = r, r = r -> rc;
( *p ) -> data = r -> data;//用左子树中最右边的节点的值覆盖要删除的节点
if( pre != r )//若p左子树有右节点
pre -> rc = r -> lc;
else//若p左子树没有右节点
( *p ) -> lc = r -> lc;
free( r );//释放节点
}
else//若无左子树
{
Link q = ( *p );
*p = ( *p ) -> rc;
free( q );
q = NULL;
}
}
void Print( Link L )
{
if( L )//中序遍历
{
Print( L -> lc );
printf( "%d ",L -> data );
Print( L -> rc );
}
}
int main( )
{
Link L = NULL;
int n,x;
while( 1 )
{
printf( "1 插入 2 中序遍历 3 查找 4 删除\n" );
char ch;
ch = getch( );
if( ch == '1' )//插入
{
printf( "请输入n:" );
scanf( "%d",&n );
insert( &L,n );
}
else if( ch == '2' )//中序遍历
{
if( L == NULL )
printf( "没有节点\n" );
else
Print( L );
}
else if( ch == '3' )//查找
{
if( L == NULL )
printf( "没有节点\n" );
else
{
printf( "请输入要查找的数x:" );
scanf( "%d",&x );
Link *p;
p = Search( &L,x );
if( p )
printf( "查找成功\n" );
else
printf( "没有%d这个节点\n",x );
}
}
else if( ch == '4' )//删除
{
printf( "请输入您要删除的数x:" );
scanf( "%d",&x );
Link *p;
p = Search( &L,x );//先看有没有这个节点
if( !p )
printf( "没有这个数" );
else
{
Delete( p ); //若有则进行删除操作
printf( "删除成功\n" );
}
}
printf( "\nOK" );
getch();
system( "cls" );
}
return 0;
}
//+-+*3##*x##x##x##/1##x##5##
本人还是新手 ,转载请注明来自Lvsi‘s home
浙公网安备 33010602011771号