天天看点

二叉排序树的相关操作二叉排序树的相关操作

二叉排序树的相关操作

文章目录

  • 二叉排序树的相关操作
    • @[toc]
    • 一:二叉排序树的构建
    • 二:二叉排序树的搜索
      • 1、递归查找目标结点,并返回地址
      • 2、查找
    • 三:插入操作
    • 四:遍历
    • 五:删除结点
    • 六:主函数

一:二叉排序树的构建

/**
 * 二叉排序树的构建
 * @param T
 * @param array     数组
 * @param numsize   数组长度
 * @return
 */
int CreatBSTTree(BSTTree* T,int* array,int numsize){
    *T = NULL;
    for (int i = 0; i < numsize; ++i) {
        InsertBST(T,array[i]);
    }
    return 1;

}
           

二:二叉排序树的搜索

1、递归查找目标结点,并返回地址

/**
 * 查找关键节点,并返回查找到的位置,否则为null
 * @param T
 * @param ele
 * @return
 */
BSTTree SearchBST_1(BSTTree T,ElemType_BST ele){
    if (T!=NULL){
        if (ele == T->data){
            return T;
        } else if (ele>T->data){
            return SearchBST_1(T->rchild,ele);
        } else if (ele<T->data){
            return SearchBST_1(T->lchild,ele);
        }
    } else{
        return NULL;
    }
}
           

2、查找

/**
 * 在T所指向的二叉排序中递归查找关键字等于ele的数据元素,若查找成功,则指针p指向该数据元素结点,并返回1,
 * 否则,p指向的是该条查找路径上的最后一个结点并返回0,指针f为指针T的双亲,初始值为NULL
 * @param T
 * @param ele
 * @param f
 * @param p
 * @return
 */
int SearchBST_2(BSTTree T,ElemType_BST ele,BSTTree f,BSTTree* p){
    if (!T){
        *p=f;
        return 0;
    } else if (ele == T->data){
        *p = T;
        return 1;
    } else if (ele > T->data){
        return SearchBST_2(T->rchild,ele,T,p);
    } else if (ele< T->data){
        return SearchBST_2(T->lchild,ele,T,p);
    }
}
           

三:插入操作

/**
 * 插入之前,先进行查找,因为,我们使用二叉排序树是就是为了查找一个元素,那么当该元素不在树中时,
 * 便需要将结点插入,而插入的路径就是查找路径
 * 插入元素
 * @param T
 * @param ele
 * @return
 */
int InsertBST(BSTTree* T,ElemType_BST ele){
    BSTTree p;
    if (!SearchBST_2(*T,ele,NULL,&p)){
        BSTTree s = (BSTTree)malloc(sizeof (BSTNode));
        s->data = ele;
        s->lchild = NULL;
        s->rchild = NULL;
        if (!p){    //表示当前待插入的排序树,一个节点都没有,带插入节点为根节点
            *T = s;
        } else if (p->data > ele){
            p->lchild = s;
        } else{
            p->rchild = s;
        }
        return 1;
    } else{
        return 0;
    }
}
           

四:遍历

使用中序遍历遍历二叉排序树可以得到一个有序的数列

/**
 * 中序遍历会得到一个有序的序列
 */
void BSTInOrder(BSTTree T){
    if (T){
        BSTInOrder(T->lchild);
        printf("\t%d",T->data);
        BSTInOrder(T->rchild);
    }
}
           

五:删除结点

/**
 * 删除操作的入口函数
 * @param T
 * @param ele
 * @return
 */
int BSTDelete(BSTTree *T,ElemType_BST ele){
    if (!(*T)){
        return 0;
    } else{
        if ((*T)->data == ele){
            return Delete(T);
        } else if ((*T)->data > ele){
            return BSTDelete(&(*T)->lchild,ele);
        } else{
            return BSTDelete(&(*T)->rchild,ele);
        }
    }
}

/**
 * 删除一个结点,使之删除之后仍然是一个二叉排序树
 *  1、如果待删除结点p是叶子节点,则直接删除
 *  2、如果待删除节点p只有左孩子或者右孩子,那么删除之后,将p结点的左孩子作为p双亲结点的左孩子,或者将p结点
 *      的右孩子作为p双亲结点的右孩子
 *  3、如果p节点同时有左孩子和右孩子,那么有以下两种操作方式:
 *      1、令结点p的左子树作为其双亲结点的左子树;结点p的右子树作为其自身直接前驱结点到右子树
 *      2、用节点p的直接前驱(或者直接后继)来代替p结点,同时在二叉排序树中对其前驱结点(或直接后继)结点做删除操作。
 *      (本代码中使用第2种方法)
 *
 * @param T
 * @return
 */
int Delete(BSTTree *p){
    BSTTree q,s;    //s来表示待删除结点p的前驱节点,q表示s的双亲结点
    if ((*p)->lchild == NULL &&(*p)->rchild == NULL){   //叶子节点,直接删除
        q = (*p);
        free(q);
    } else if (!(*p)->rchild){      //表示右子树为空,左子树不为空
        (*p)->data  = (*p)->lchild->data;
        (*p)->lchild = NULL;
        free((*p)->lchild);
    } else if (!(*p)->lchild){  //表示左子树为空,右子树不为空
        (*p)->data = (*p)->rchild->data;
        (*p)->rchild = NULL;
        free((*p)->rchild);
    } else{     //左右子树借不为空,使用第二种方式
       //寻找当前节点的前驱节点
       q = *p;
       s = q->lchild;
        while (s->rchild){
            q = s;
            s = s->rchild;
        }
        //赋值
        (*p)->data = s->data;

        //s必然没有右子树,只需要判断s是否有左子树
        if (s->lchild!=NULL){
            s->data = s->lchild->data;
            s->lchild = NULL;
            free(s->lchild);
        } else{
            if (q!=(*p)){
                q->rchild = NULL;
                free(s);
            } else{
                q->lchild = NULL;
                free(s);
            }
        }
    }
    return 1;
}
           

对于删除操作,详细的解析可以看这篇博客:

二叉排序树

六:主函数

void main(){
    BSTTree Tree;
    int array[] = {7,3,9,1,5,8,10,2,4,6,11};
    CreatBSTTree(&Tree,array,sizeof (array)/4);
    printf("the PreBST:");
    BSTPreOrder(Tree);
    printf("\n");
    printf("the inBSTOrder:");
    BSTInOrder(Tree);
    printf("\n");
    BSTTree node = SearchBST_1(Tree,7);
    if (node){
        printf("node:%d\n",node->data);
        if (node->rchild){
            printf("node's child:%d\n",node->rchild->data);
        }
    }
//    Delete(&node);
//    BSTInOrder(Tree);
    BSTDelete(&Tree,5);
    printf("After delete:");
    BSTInOrder(Tree);
    printf("\n");
}
           

结果展示:

二叉排序树的相关操作二叉排序树的相关操作

测试二叉排序树:

二叉排序树的相关操作二叉排序树的相关操作

继续阅读