题意:搜索二叉树的常规操作。
思路:一般有两种,一种是递归调用,另一种是非递归的方法。我采用的是非递归的方法。
注意点:
1删除操作,一个节点左右都不为空,是将结点的右子树接到左子树的最大值的右孩子。
2访问节点时,一定要注意该节点是否为空,如果为空千万不要去访问节点的数据,不然会出错。
#include <stdio.h>
#include <stdlib.h>
#include<malloc.h>
typedef int ElementType;
typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
ElementType Data;
BinTree Left;
BinTree Right;
};
void PreorderTraversal( BinTree BT ) /* 先序遍历,由裁判实现,细节不表 */
{
if(BT){
printf("%d ",BT->Data);
PreorderTraversal(BT->Left);
PreorderTraversal(BT->Right);
}
}
void InorderTraversal( BinTree BT ) /* 中序遍历,由裁判实现,细节不表 */
{
if(BT){
InorderTraversal(BT->Left);
printf("%d ",BT->Data);
InorderTraversal(BT->Right);
}
}
BinTree Insert( BinTree BST, ElementType X );
BinTree Delete( BinTree BST, ElementType X );
Position Find( BinTree BST, ElementType X );
Position FindMin( BinTree BST );
Position FindMax( BinTree BST );
int main()
{
BinTree BST, MinP, MaxP, Tmp;
ElementType X;
int N, i;
BST = NULL;
scanf("%d", &N);
for ( i=0; i<N; i++ ) {
scanf("%d", &X);
BST = Insert(BST, X);
}
printf("Preorder:"); PreorderTraversal(BST); printf("\n");
MinP = FindMin(BST);
MaxP = FindMax(BST);
scanf("%d", &N);
for( i=0; i<N; i++ ) {
scanf("%d", &X);
Tmp = Find(BST, X);
if (Tmp == NULL) printf("%d is not found\n", X);
else {
printf("%d is found\n", Tmp->Data);
if (Tmp==MinP) printf("%d is the smallest key\n", Tmp->Data);
if (Tmp==MaxP) printf("%d is the largest key\n", Tmp->Data);
}
}
scanf("%d", &N);
for( i=0; i<N; i++ ) {
scanf("%d", &X);
BST = Delete(BST, X);
}
printf("Inorder:"); InorderTraversal(BST); printf("\n");
return 0;
}
BinTree Insert( BinTree BST, ElementType X ) //插入
{
BinTree p,pp,q=(BinTree)malloc(sizeof(BinTree)); //q插入的节点 ,pp插入节点q的父亲结点
q->Data=X;q->Left=NULL;q->Right=NULL;
if(!BST)BST=q;
else{
p=BST;
while(p){
if(X<p->Data){pp=p;p=p->Left;}
else{pp=p;p=p->Right;}
}
if(X<pp->Data)pp->Left=q;
else pp->Right=q;
}
return BST;
}
Position Find( BinTree BST, ElementType X ) //查询
{
BinTree p=BST;
while(p){
if(p->Data==X)break;
else if(X<p->Data)p=p->Left;
else p=p->Right;
}
return p;
}
Position FindMin( BinTree BST )//查找最小值
{
BinTree p=BST;
while(p&&p->Left){ //原来是p->Left&&p
p=p->Left;
}
return p;
}
Position FindMax( BinTree BST ) //查找最大值
{
BinTree p=BST;
while(p&&p->Right){
p=p->Right;
}
return p;
}
BinTree Delete( BinTree BST, ElementType X )
{
BinTree q,qq,pp=NULL,p;//p删除结点,pp删除结点的父亲结点
p=BST;
while(p){ //查找删除结点的位置
if(X==p->Data)break;
else if(X<p->Data){pp=p;p=p->Left;}
else{pp=p;p=p->Right;}
}
if(!p)printf("Not Found\n");
else{
if(!p->Left&&!p->Right){ //叶子节点
if(!pp){BST=pp;}
else{
pp->Left=NULL;
pp->Right=NULL;
}
}
else if(!p->Right&&p->Left){ //右子树为空,左子树不为空
if(!pp){BST=p->Left;}
else{
if(pp->Left&&pp->Left->Data==p->Data){pp->Left=p->Left;} //注意pp->Left可能为空
else {pp->Right=p->Left;}
}
}
else if(!p->Left&&p->Right){ //左子树为空,右子树不为空
if(!pp){BST=p->Right;}
else{
if(pp->Left&&pp->Left->Data==p->Data){pp->Left=p->Right;}
else {pp->Right=p->Right;}
}
}
else if(p->Left&&p->Right){ //左右子树都不为空 ,将右子树移动到左子树最大值的右子树。
qq=p->Left;
while(qq->Right)qq=qq->Right;//qq左子树最大的节点
qq->Right=p->Right;
if(!pp){BST=p->Left;}
else{
if(pp->Left->Data==p->Data){pp->Left=p->Left;}
else {pp->Right=p->Left;}
}
}
free(p);
}
return BST;
}
