二叉排序树 插入 删除 遍历
这两天要弄数据结构考试,就在写二叉排序树
二叉排序树总共三个操作:插入,查找,删除,遍历;
先提醒对于插入,删除等要改变这棵树的操作都要用二维指针,否则不能改变,而遍历( 打印 ),查找( 这里的查找因为要为删除服务,所以用了二维指针,其实纯粹的查找是不需要的 )不需改变他的值,所以不用二维指针
插入:小的往左边放,大的往右边放,相等的直接不要,然后递归处理就可以了。
查找:如果查找的值等于当前节点,则返回当前节点,若查找的值比当前节点小则在当前节点的左子树中去找,若比当前节点大,则在当前右子树中去找,若差找不成功,返回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