算法笔记:二叉搜索树BST(未完待续)

来源:互联网 发布:linux zip 解压乱码 编辑:程序博客网 时间:2024/06/07 06:02

专题:二叉搜索树BST

一、定义

        二叉搜索树(Binary Search Tree),也称有序二叉树或排序二叉树,是指一棵空树或者具有下列性质的二叉树:

        1. 若任意节点的左子树不空,则左子树上所有节点的值均小于它的根节点的值;

        2. 若任意节点的右子树不空,则右子树上所有节点的值均大于它的根节点的值;

        3. 任意节点的左、右子树也分别为二叉搜索树。

        也就是说:设x是二叉搜索树中的一个节点。

        如果y是x的左子树中的一个节点,则有y.key<x.key;

        如果y是x的右子树中的一个节点,则有y.key>x.key。

二、结构与基本操作

1. 二叉搜索树具有很高的灵活性,对其优化可以生成平衡二叉树,红黑树等高效的查找和插入数据结构。

2. 基本操作:

(1)查找:查询是否包含某个数值

        该查找方法也叫“树表查找”。类似二分查找,将待查找数值val和当前节点的值key比较:

        若val=key,表示找到,返回该值或者找到的信息;

        若val<key,则往左儿子节点走,在左子树中继续查找;

        若val>key,则往右儿子节点走,在右子树中继续查找。

(2)插入:向二叉搜索树中插入某个节点

        按照上述查找数值的方法试图查找这个数值的节点,就可以知道其对应的节点的所在位置,之后在那个位置插入新的节点即可。

        【该过程可分解为”查找->插入”两步】

(3)删除:向二叉搜索树中删除某个节点

        一般来说,需要根据下面几种情况分别进行处理:

        ①  需要删除的节点没有左儿子,那么就把右儿子提上去

        ②  需要删除的节点的左儿子没有右儿子,那么就把左儿子提上去

        ③  以上两种情况都不满足的话,就把左儿子的子孙中最大的节点提到需要删除的节点上。

        【该过程可分解为”查找->删除->调整”三步】

3. 一个特殊特性:对二叉搜索树进行中序遍历,可以得到节点值的有序序列。

三、复杂度分析

        不论以上哪种操作,所花的时间都和树的高度成正比。因此,如果共有n个元素,则平均每次操作需要O(logn)的时间。

四、代码实现

#include <stdio.h>#include <stdlib.h>#define maxn 1010int n;               //待插入BST的元素数int elem[maxn];      //待插入BST的元素typedef struct node  //自定义二叉搜索树的节点{    int data;        //键值    node *lchild;    //左孩子    node *rchild;    //右孩子} BST;void Init(BST *&b)   //初始化BST(空树){    b=NULL;}BST *Insert(BST *&b,int x)   //向BST中插入元素x,返回BST结构体的指针{    if(b==NULL)      //当前节点为空时,创建新节点    {        b=(BST *)malloc(sizeof(BST));        b->data=x;        b->lchild=b->rchild=NULL;    }    else    {        if(x<b->data)//待插入节点比当前节点小,在左子树中插入            b->lchild=Insert(b->lchild,x);        else     //否则在右子树中插入            b->rchild=Insert(b->rchild,x);    }    return b;}int Find(BST *b,int x)        //在BST中查找元素x{    if(b==NULL)   //当前节点为空,表示未找到,返回0        return 0;    else    {        if(b->data==x)    //当前节点为待查找节点,表示找到,返回1            return 1;        else if(x<b->data)//否则,在左子树中继续查找            return Find(b->lchild,x);        else      //在右子树中继续查找            return Find(b->rchild,x);    }}BST *Remove(BST *p,int x)   //在BST中删除元素x,返回BST结构体的指针{    BST *q,*r;    //首先查找待删除节点x    if(p==NULL)         //当前节点为空,表示找不到,直接返回空        return NULL;    else if(x<p->data)  //待删除节点比当前节点小,在左子树中删除        p->lchild=Remove(p->lchild,x);    else if(x>p->data)  //待插入节点比当前节点大,在右子树中删除        p->rchild=Remove(p->rchild,x);    //然后分别处理可能出现的三种情况    else if(p->lchild==NULL)  //需要删除的节点没有左儿子    {        q=p->rchild;    //将右儿子提上去        free(p);        return q;    }    else if(p->lchild->rchild==NULL)  //需要删除的节点的左儿子没有右儿子    {        q=p->lchild;    //将左儿子提上去        q->rchild=p->rchild;        free(p);        return q;    }    else    //其他情况    {        for(q=p->lchild;q->rchild->rchild!=NULL;q=q->rchild); //将左儿子的子孙中最大的节点提到需要删除的节点上        r=q->rchild;        q->rchild=r->lchild;        r->lchild=p->lchild;        r->rchild=p->rchild;        free(p);        return r;    }    return p;}void PreOrderBST(BST *b)      //先序遍历BST{    if(b!=NULL)    {        printf("%d ",b->data);        PreOrderBST(b->lchild);        PreOrderBST(b->rchild);    }}void InOrderBST(BST *b)       //中序遍历BST{    if(b!=NULL)    {        InOrderBST(b->lchild);        printf("%d ",b->data);        InOrderBST(b->rchild);    }}void PostOrderBST(BST *b)     //后序遍历BST{    if(b!=NULL)    {        PostOrderBST(b->lchild);        PostOrderBST(b->rchild);        printf("%d ",b->data);    }}void PrintOrder(BST *b)       //打印BST先中后序遍历序列{    printf("PreOrderBST:");    PreOrderBST(b);    printf("\n");    printf("InOrderBST:");    InOrderBST(b);    printf("\n");    printf("PostOrderBST:");    PostOrderBST(b);    printf("\n");}int main(){    int i;    BST *b;    Init(b);         //初始化BST为空(很重要!)    scanf("%d",&n);    for(i=0;i<n;i++) //这里建立BST采用根据输入序列,逐个插入已初始化为空的树实现的    {        scanf("%d",&elem[i]);        Insert(b,elem[i]);    }    printf("Succeed!\n");    PrintOrder(b);    printf("%d %d %d %d\n",Find(b,2),Find(b,6),Find(b,-3),Find(b,11));    Remove(b,7);    printf("Succeed!\n");    PrintOrder(b);    return 0;}/*测试数据104 2 1 0 3 5 9 7 6 8838 26 62 94 35 50 28 55*/


原创粉丝点击