数据结构 04-树7 二叉搜索树的操作集 (30 分)

本题要求实现给定二叉搜索树的5种常用操作。

函数接口定义:

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 );
 

其中BinTree结构定义如下:

typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
    ElementType Data;
    BinTree Left;
    BinTree Right;
};
 
  • 函数InsertX插入二叉搜索树BST并返回结果树的根结点指针;
  • 函数DeleteX从二叉搜索树BST中删除,并返回结果树的根结点指针;如果X不在树中,则打印一行Not Found并返回原树的根结点指针;
  • 函数Find在二叉搜索树BST中找到X,返回该结点的指针;如果找不到则返回空指针;
  • 函数FindMin返回二叉搜索树BST中最小元结点的指针;
  • 函数FindMax返回二叉搜索树BST中最大元结点的指针。

裁判测试程序样例:

#include <stdio.h>
#include <stdlib.h>

typedef int ElementType;
typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
    ElementType Data;
    BinTree Left;
    BinTree Right;
};

void PreorderTraversal( BinTree BT ); /* 先序遍历,由裁判实现,细节不表 */
void InorderTraversal( BinTree BT );  /* 中序遍历,由裁判实现,细节不表 */

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;
}
/* 你的代码将被嵌在这里 */
 

输入样例:

10
5 8 6 2 4 1 0 10 9 7
5
6 3 10 0 5
5
5 7 0 10 3
 

输出样例:

Preorder: 5 2 1 0 4 8 6 7 10 9
6 is found
3 is not found
10 is found
10 is the largest key
0 is found
0 is the smallest key
5 is found
Not Found
Inorder: 1 2 4 6 8 9

 

 

BinTree Insert( BinTree BST, ElementType X ){
    BinTree p=BST;
    BinTree parent=NULL;
    BinTree newnode=(BinTree)malloc(sizeof(struct TNode));
    newnode->Data=X;
    newnode->Left=NULL;
    newnode->Right=NULL;
    while(p!=NULL){//寻找合适位置插入
        parent=p;
        if(X<p->Data){
            p=p->Left;
        }else{
            p=p->Right;
        }
    }
    if(parent==NULL){
        BST=newnode;
    }else if(X<parent->Data){
        parent->Left=newnode;
    }else{
        parent->Right=newnode;
    }
    return BST;
}

BinTree Delete( BinTree BST, ElementType X ){
    BinTree p=BST,parent=NULL;//如果父节点为NULL说明是根结点
    int flag=1;
    while(p!=NULL){
        if(X<p->Data){//小于从左子树找
            parent=p;//标记父节点
            p=p->Left;
        }else if(X>p->Data){//大于从右子树找
            parent=p;
            p=p->Right;
        }else{//找到了要删除的结点
            flag=0;//标记找到了结点
            if(p->Left==NULL&&p->Right==NULL){//首先处理叶子结点
                if(parent==NULL){//要删除的结点是 只有一个结点的根结点 直接返回空树
                    BST=NULL;//根节点置为空
                    break;
                }else{//非根的叶结点
                    //删除的结点小于父结点 则是左子结点 把父结点的左子结点置为NULL 反之是右子结点
                    (p->Data<parent->Data)?(parent->Left=NULL):(parent->Right=NULL);
                    break;
                }
            }else if(p->Left==NULL&&p->Right!=NULL){//要删除的结点只有 右子树
                if(parent==NULL){//该结点是根结点 没有父结点
                    BST=BST->Right;
                    break;
                }else{//非根结点
                    //删除的结点小于父结点是左子结点 把父结点的左子结点指向删除结点的右子树
                    //反之是父结点的右子结点指向删除结点的右子树
                    (p->Data<parent->Data)?(parent->Left=p->Right):(parent->Right=p->Right);
                    break;
                }
            }else if(p->Left!=NULL&&p->Right==NULL){//要删除的结点只有左子树
                if(parent==NULL){//该结点是根结点 没有父结点 没有右子树
                    BST=BST->Left;
                    break;
                }else {
                     //删除的结点小于父结点是左子结点 把父结点的左子结点指向删除结点的左子树
                    //反之是父结点的右子结点指向删除结点的左子树
                    (p->Data<parent->Data)?(parent->Left=p->Left):(parent->Right=p->Left);
                    break;
                   //
                }
            }else{//要删除的结点有左子树同时有右子树
                    BinTree tempP=p;//需要一个新的结点 暂存p结点
                    //这里寻找p的前驱作为替换结点 也就是左子树的最大结点
                    p=p->Left;//从左子树开始找左子树的最大结点
                    while(p->Right!=NULL){//保存父结点的同时 一直找到左子树的最大值
                        parent=p;
                        p=p->Right;
                    }
                    //父结点的右子树指向 最大值的的左子树
                    parent->Right=p->Left;
                    //然后将最大值结点的左右子树 指向 删除结点的左右子树
                    tempP->Data=p->Data;
                    break;
            }
        }
    }
    if(flag){
        printf("Not Found\n");
    }
    return BST;
}

Position Find( BinTree BST, ElementType X ){
    BinTree p=BST;
    while(p!=NULL){
        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!=NULL){
        if(p->Left==NULL){//直到最后一个左子树为空的结点就是最小结点
            break;
        }else{
            p=p->Left;
        }
    }
    return p;
}
Position FindMax( BinTree BST ){
    BinTree p=BST;
    while(p!=NULL){
        if(p->Right==NULL){//直到最后一个右子树为空的结点就是最大结点
            break;
        }else{
            p=p->Right;
        }
    }
    return p;
}

 

上一篇:938 range sum of BST


下一篇:二叉搜索树(C语言实现)