二叉排序树

使用c实现.

二叉排序树: 左子树小于根结点, 右子树大于根结点

因为二叉排序的特点 不难看出 中序遍历之后的结果就是有序的(从小到大)
搜索的时候如果大于根结点就遍历右子树,小于根结点就遍历左子树,否则就查找成功.

总结:

二叉排序树是链式方式存储,保持了链接存储结构在执行插入和删除操作是不用移动元素的优点, 只要找到合适的插入和删除位置后, 仅需要修改链接指针即可,
插入删除的时间性能比较好
超找的次数就是从根结点到要查找的结点的路径, 其比较次数等于给定结点在二叉树的层数,
最少查找次数是O(1), 做多也不会超过树的深度
所以查找的性能取决于二叉排序树的形状.

//二叉排序树
#include <stdio.h>
#include <stdlib.h> 
#define TRUE 1
#define FALSE 0

typedef int Status;

//二叉树的结构体定义
typedef struct BiTNode{
    int data;
    struct BiTNode *lchild, *rchild;    //左右孩子指针 
}BiTNode, *BiTree; 

//二叉排序树的查找实现
/*
    递归实现, 查找二叉排序树T中是否存在key
    指针f是T的双亲, 初始值是null
    查找成功,用指针p指向给数据的结点, 返回true
    查找失败,指针p指向查找路径上最后一次访问的结点, 返回false 
    num 查找的次数 
*/
Status searchBST(BiTree T, int key, BiTree f, BiTree *p, int *num){
    (*num) ++; 
    if(!T){         //查找失败 
        *p = f;
        return FALSE; 
    }else if(T->data == key){   //查找成功 
        *p = T;
        return TRUE; 
    }else if(T->data > key){
        searchBST(T->lchild, key, T, p, num);       //在左子树中查找 
    }else{
        searchBST(T->rchild, key, T, p, num);       //在右子树中查找
    }
} 

//插入
/*
    key不在树中,则插入 
*/
insertBST(BiTree *T, int key){
    BiTree p, s; 
    int num = 0;
    if(!searchBST(*T, key, NULL, &p, &num)) {   //查找不成功 
        s = (BiTree)malloc(sizeof(BiTNode));
        s->data = key;
        s->lchild = s->rchild = NULL;
        if(!p){
            *T = s;     //根结点 
        }else if(p->data > key){    //新的结点插入到左子树中 
            p->lchild = s; 
        } else{
            p->rchild = s; 
        }
        return TRUE; 
    }
    return FALSE;
} 

//中序遍历二叉排序树
void inOrderTraverse(BiTree T){
    if(T == NULL){
        return; 
    }
    inOrderTraverse(T->lchild);
    printf("%d ", T->data);
    inOrderTraverse(T->rchild);
} 

//前序遍历二叉排序树
void preOrderTraverse(BiTree T){
    if(T == NULL){
        return; 
    }
    printf("%d ", T->data);
    preOrderTraverse(T->lchild);
    preOrderTraverse(T->rchild);
} 

//后序遍历二叉排序树
void postOrderTraverse(BiTree T){
    if(T == NULL){
        return; 
    }
    postOrderTraverse(T->lchild);
    postOrderTraverse(T->rchild);
    printf("%d ", T->data);
} 

//二叉排序树的删除 重构左右子树
Status delete(BiTree *p) {
    BiTree q, s;
    if((*p)->rchild == NULL){       //右子树为空 只需重构左子树 
        q = *p;
        *p = (*p)->lchild;
        free(q) ;
    }else if((*p)->lchild == NULL){     //左子树为空 只需重构右子树 
        q = *p;
        *p = (*p)->rchild;
        free(q) ;
    }else{          //左右子树都不为null 
        q = *p;
        s = (*p)->lchild;
        while(s->rchild){   //找左子树的最大值 
            q = s;
            s = s->rchild; 
        }
        (*p)->data = s->data;   //将s的值直接覆盖要删除的结点
        if(q != *p){
            q->rchild = s->lchild;  //重构q的右子树 
        } else{
            q->lchild = s->lchild;  //重构q的左子树 
        }
        free(s); 
    } 
    return TRUE;
}
//二叉排序树的删除 找结点 
/*
    二叉排序树中存在关键字是key的则删除 元素结点 返回true否则返回false 
*/
Status deleteBST(BiTree *T, int key){
    if(!*T){
        return FALSE;   //不存在关键字key的数据元素 
    }else{
        if((*T)->data == key){
            return delete(T);
        }else if((*T)->data > key){
            return deleteBST(&((*T)->lchild), key);
        } else{
            return deleteBST(&((*T)->rchild), key);
        }
    }
} 

//遍历
void travese(BiTree T){
    printf("前序遍历是: ");
    preOrderTraverse(T);
    printf("\n");
    printf("中序遍历是: ");
    inOrderTraverse(T);
    printf("\n");
    printf("后序遍历是: ");
    postOrderTraverse(T);
    printf("\n");
} 
Status main(void){
    BiTree T = NULL, p;
    int arr[10] = {1,34,3,234,2,6,343,43,4,32};
    int i;
    for(i = 0; i < 10 ; i ++){
        insertBST(&T, arr[i]);
    } 
    int option = 1, key = 0, res = 0, num = 0;
    printf(" 1. 查找数据\n 2. 遍历数据\n 3. 删除数据\n 0. 退出\n");
    while(option){
        scanf("%d", &option);
        switch(option){
            case 1:
                num = 0; 
                printf("请输入要查找的数据\n");
                scanf("%d", &key);
                res = searchBST(T, key, NULL, &p, &num);
                if(res == TRUE){
                    printf("查找成功 查找的次数是: %d\n", num);
                }else{
                    printf("查找失败 查找的次数是: %d\n", num);
                } 
                break;
            case 2:
                travese(T);
                break;
            case 3:
                printf("请输入要删除的数据\n");
                scanf("%d", &key);
                res= deleteBST(&T, key);
                if(res == TRUE){
                    printf("删除成功\n");
                    travese(T);
                }else{
                    printf("删除失败 删除的数据不存在\n");
                } 
                break;
            case 0:
                return TRUE;
                break;
            default:
                 printf(" 1. 查找数据\n 2. 遍历数据\n 0. 退出\n");
                 break;
        }
    }
    return TRUE;
} 
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值