第四章——二叉搜索树

二叉树,虽然方便遍历和初始化存储,但是我们如果要插入呢,要查找里面的数据呢,怎么办,这就需要我们良好的设计这个树了,我们在插入的时候怎麽插,我们可以设计出这样一种树,它的左子树必须小于它的父结点,它的右子树必须大于它的父结点,就这样,我们就可以构造出一颗可以方便我们查找的树了,也可以方便我们插入,在我们插入时,我们只需要将插入的数据跟结点值做比较,如果比他小,就继续跟他的左子树比较,如果比他它大,就跟它的右子树比较,这样依次循环比较,直到这个结点为空,则插入进去(感觉我描述得不是很清楚,我们看代码吧):

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

typedef struct TNode {
    int data;
    struct TNode *lchild;
    struct TNode *rchild;
}TNode,*Tree;

void InitTree (Tree *T);//初始化树。
void Insert1 (int x, Tree *T);//插入一个数值进去。(我用的二重指针进行的插入)
void Pre (Tree T);//先序遍历树。
Tree Insert (int x, Tree T);//插入一个数值进去。
Tree Find (int x, Tree T);//查找x所在的结点。
Tree FindMin (Tree T);//查找最小值。
Tree FindMax (Tree T);//查找这颗树的最大值。
Tree Delete (int x, Tree T);//删除x所在的结点。
void Delete1 (int x, Tree *T);//删除x所在的结点。(我用的二重指针进行删除的)
/*插入和删除我都用了两种不同的形式,主要是想让自己加强对指针的运用。*/


int main (){//主函数是为用来验证我写的函数功能是否能实现。
    Tree T;
    InitTree (&T);
    Insert1 (1,&T);
    Insert1(2,&T);
    T  = Insert (3,T);
    T = Insert (4,T);
    Pre (T);
    Tree temp;
    temp = FindMin(T);
    printf("min is %d\n",temp->data);
    temp = FindMax(T);
    printf("max is %d\n",temp->data);
    temp = Find (2,T);
    printf("2 is %d \n",temp->data);
    T = Delete (2,T);
    Delete1 (1,&T);
    Pre (T);

    return 0;
}

void Delete1 (int x, Tree *T)
{
    Tree temp;
    if (!(*T)) printf("find failure!\n");
    else if (x < (*T)->data) {//如果x小于该结点的值,我们就将x和左子树进行删除操作。
        Delete1(x,&(*T)->lchild);
    }else if(x > (*T)->data) {//同上。
        Delete1 (x,&(*T)->rchild);
    }else if((*T)->rchild && (*T)->lchild) {//当该删除结点有左右子树时,我们就找到右子树的最小值来代替。
            temp = FindMin ((*T)->rchild);
            (*T)->data = temp->data;
            Delete1 (temp->data,&(*T)->rchild);//然后我们删除游子的最小值。
    }else {
        temp = *T;
        if (!(*T)->lchild) {//当左子不存在或者两个结点都不存在时。
            (*T) = (*T)->rchild;//我们用右子树的结点代替。
        }else if(!(*T)->rchild) {//同上。
            (*T) = (*T)->lchild;
        }
        free (temp);
    }
    
}

Tree Delete (int x, Tree T)
{
    Tree temp;
    if (!T) printf("find failure!\n");
    else if (x < T->data) {
        T->lchild = Delete (x, T->lchild);
    }else if (x > T->data) {
        T->rchild = Delete (x, T->rchild);
    }else if (T->lchild && T->rchild) {
            temp = FindMin(T->rchild);
            T->data = temp->data;
            T->rchild = Delete(temp->data,T->rchild);
    }else {
        temp = T;
        if (!T->lchild) {
            T = T->rchild;
        }else if (!T->rchild) {
            T = T->lchild;
        }
    }

    return T;
}

Tree Find (int x, Tree T)
{
    while (T) {
        if (x < T->data) {
            T = T->lchild;
        }else if (x > T->data) {
            T = T->rchild;
        }else {
            return T;
        }
    }

    return NULL;
}

Tree FindMin (Tree T)
{
    if (!T) return NULL;
    while (T->lchild ) {
        T = T->lchild;
    }

    return T;
}

Tree FindMax (Tree T)
{
    if (!T ) return NULL;
    else if (!T->rchild) return T;
    else return FindMax(T->rchild);
}

void Pre (Tree T)
{
    if (T) {
        printf("%d ",T->data);
        Pre (T->lchild);
        Pre (T->rchild);
    }
}

void InitTree (Tree *T)
{
    *T = NULL;
}

Tree Insert (int x, Tree T)
{
    if (!T) {//若该结点为空,我们就为该结点申请空间并赋值。
        T = (Tree) malloc(sizeof(TNode));
        T->data = x;
        T->lchild = T->rchild = NULL;
    }else if (x > T->data) {//若大于该结点,就插入它的右子树。
        T->rchild = Insert (x,T->rchild);
    }else if (x < T->data) {//若小于该结点,就插入它的左子树。
        T->lchild = Insert (x,T->lchild);
    }

    return T;
}


void Insert1 (int x, Tree *T)
{
    if (!(*T)) {
        *T = (Tree) malloc (sizeof(TNode));
        (*T)->data = x;
        (*T)->lchild = (*T)->rchild = NULL;
    }else if (x < (*T)->data) {
            Insert1 (x,&(*T)->lchild);
    }else if (x > (*T)->data) {
            Insert1 (x,&(*T)->rchild);
    }
}

 

以上就是二叉搜索树的基本操作,期待下一次!

posted @ 2020-10-18 21:39  lookfd  阅读(53)  评论(0编辑  收藏