xiejunyan的平衡二叉树

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW -1
typedef int Status;
typedef int KeyType;

typedef struct RcdType {
    KeyType key;
}RcdType;
typedef struct BBSTNode {
    RcdType data;
    int height;
    struct BBSTNode* lchild, *rchild;
}BBSTNode, * BBSTree;

int max(int i, int j) {
    return (i > j) ? i : j;
}

Status InitAVL(BBSTree& T) {
    T = NULL;
    return OK;
}

void DestroyBBST(BBSTree& T) {

    //采用递归的方法后序遍历平衡二叉树,访问结点时销毁该结点。
        if (NULL != T) {
            DestroyBBST(T->lchild);
            DestroyBBST(T->rchild);

            free(T);
        }
}

void Preorder(BBSTree& T){
    //先序遍历
     if (NULL != T) {
            printf("%d ", T->data.key);
     
            Preorder(T->lchild);
            Preorder(T->rchild);
        }
}

void Postorder(BBSTree& T){
    //后序遍历
     if (NULL != T) {
            Postorder(T->lchild);
            Postorder(T->rchild);

            printf("%d ", T->data.key);
        }
}

void Inorder(BBSTree& T){
    //中序遍历
     if (NULL != T) {
            Inorder(T->lchild);
            
            printf("%d ", T->data.key);
            
            Inorder(T->rchild);
        }
}

void JudgeBBST(BBSTree& T, Status &ok_error) {

    //判断一棵树是否为平衡二叉树
        if (NULL != T && ok_error) {
            JudgeBBST(T->lchild, ok_error);
            JudgeBBST(T->rchild, ok_error);

            if (T->lchild->height - T->rchild->height >= 2 || T->rchild->height - T->lchild->height >= 2) {
                ok_error = ERROR;
            }
        }
}
void LL_rotate(BBSTree& T) {
    BBSTree lc;
    lc = T->lchild;
    int lclcH = lc->lchild->height;
    int lcrcH = lc->rchild->height;
    int rcH = T->rchild->height;//先把高度储存起来

    T->lchild = lc->rchild;
    lc->rchild = T;
    T = lc;//完成变换

    T->rchild->height = max(lcrcH, rcH) + 1;
    T->height = max(lclcH, T->rchild->height) + 1;//完成高度修改
}
void RR_rotate(BBSTree& T) {
    BBSTree rc;
    rc = T->rchild;
    int lcH = T->lchild->height;
    int rclcH = rc->lchild->height;
    int rcrcH = rc->rchild->height;//先把高度储存起来

    T->rchild = rc->lchild;
    rc->lchild = T;
    T = rc;//完成变换

    T->lchild->height = max(lcH, rclcH) + 1;
    T->height = max(rcrcH, T->lchild->height) + 1;//完成高度修改
}
void LR_rotate(BBSTree& T) {
    RR_rotate(T->lchild);
    LL_rotate(T);
}
void RL_rotate(BBSTree& T) {
    LL_rotate(T->rchild);
    RR_rotate(T);
}
void InsertAVL(BBSTree& T, RcdType e,Status &ok_error) {
    //结束:到达叶子,或已有该值结点存在则不插入
    //分解:插入的值小于当前结点左递归插入,大于则右递归插入
    //组合:在逐层回溯的时候,调整平衡

    if (NULL == T) {
        T = (BBSTree)malloc(sizeof(BBSTNode));
        T->data = e;
        T->height = 1;
        T->lchild = T->rchild = NULL;
        ok_error = OK;
    }
    else if (T->data.key == e.key) ok_error = ERROR;
    else if (e.key < T->data.key) {
        InsertAVL(T->lchild, e, ok_error);
        if (T->lchild->height - T->rchild->height == 2) {
            if (e.key < T->lchild->data.key) LL_rotate(T);
            else LR_rotate(T);
        }
        else T->height = max(T->lchild->height, T->rchild->height) + 1;
    }
    else if (e.key > T ->data.key) {
        InsertAVL(T ->rchild, e, ok_error);
        if (T->rchild->height - T->lchild->height == 2) {
            if (e.key > T->rchild->data.key) RR_rotate(T);
            else RL_rotate(T);
        }
        else T->height = max(T->lchild->height, T->rchild->height) + 1;
    }
}

void L_rotate(BBSTree& T) {
    if (T->lchild->rchild->height > T->lchild->lchild->height) {
        LR_rotate(T);
    }
    else LL_rotate(T);
}
void R_rotate(BBSTree& T) {
    if (T->rchild->lchild->height > T->rchild->rchild->height) {
        RL_rotate(T);
    }
    else RR_rotate(T);
}
RcdType find_maxleft(BBSTree lc) { 
    //用于在当前要删除结点左右子树都不为空且左子树高或一样高,的情况下找到当前要删除结点直接前驱
    while (NULL != lc->rchild) {
        lc = lc->rchild;
    }
    return lc->data;
}
RcdType find_minright(BBSTree rc) {
    //用于在当前要删除结点左右子树都不为空且右子树高,的情况下找到当前要删除结点直接后驱
    while (NULL != rc->lchild) {
        rc = rc ->lchild;
    }
    return rc->data;
}


void DeleteAVL(BBSTree& T, RcdType e, Status& ok_error, Status& can_end) {
    //结束:找到要删的结点,或到NULL结点
    //分解:要删的结点小于当前结点,左递归删除,大于则右递归删除
    //组合:从被删结点的“父节点”开始,逐层回溯,检查是否不平衡;若不平衡则调整,到根结点,或“调整后树的高度没有变化”就结束。
    if (NULL == T) {
        ok_error = ERROR;
        can_end = TRUE;
    }
    else if (T->data.key == e.key) {
        if (NULL == T->rchild) {//叶子结点,和仅右子树为空的情况
            BBSTree temp = T;
            T = T->lchild;
            free(temp);
            ok_error = OK;
        }
        else if (NULL == T->lchild) {//仅左子树为空的情况
            BBSTree temp = T;
            T = T->rchild;
            free(temp);
            ok_error = OK;
        }
        else {//左右结点都不为空的情况
            if (T->lchild->height >= T->rchild->height) {
                RcdType temp_e;
                temp_e = find_maxleft(T->lchild);
                T->data = temp_e;//仅赋值,属于“假删除”
                Status can_end_temp = FALSE;
                DeleteAVL(T->lchild, temp_e, ok_error, can_end_temp);
                T->height = max(T->lchild->height, T->rchild->height) + 1; //及时调整高度,否则回溯到父节点
            }
            else {
                RcdType temp_e;
                temp_e = find_minright(T->rchild);
                T->data = temp_e;//仅赋值,属于“假删除”
                Status can_end_temp = FALSE;
                DeleteAVL(T->rchild, temp_e, ok_error, can_end_temp);
                T->height = max(T->lchild->height, T->rchild->height) + 1;//及时调整高度,否则回溯到父节点
            }
        }
    }
    else if (e.key < T->data.key) { 
        DeleteAVL(T->lchild, e, ok_error, can_end);
        if(!can_end){
            if (T->rchild->height - T->lchild->height == 2) {
                R_rotate(T);
            }
            else {  //如果调整之后当前结点高度没有变化,则不必要向上回溯调整
                int old_height = T->height;
                T->height = max(T->lchild->height, T->rchild->height) + 1; 
                can_end = (old_height == T->height) ? TRUE : FALSE;
            }
        }
    }
    else {
        DeleteAVL(T->rchild, e, ok_error, can_end);
        if (!can_end) {
            if (T->lchild->height - T->rchild->height == 2) {
                L_rotate(T);
            }
            else {  //如果调整之后当前结点高度没有变化,则不必要向上回溯调整
                int old_height = T->height;
                T->height = max(T->lchild->height, T->rchild->height) + 1;
                can_end = (old_height == T->height) ? TRUE : FALSE;
            }
        }
    }
}




BBSTree SearchBBST(BBSTree T, KeyType key) {
    //在平衡二叉树中查找某个值
    if (NULL == T) return NULL;
    else if (T->data.key == key) return T;
    else if (key < T->data.key)  return SearchBBST(T->lchild, key);
    else return SearchBBST(T->rchild, key);
}


                                  
int main()
{
    BBSTree T;
    InitAVL(T);
    Status ok_error = OK;
    Status can_end = FALSE;
    RcdType e; e.key = 0;
    int search_key = 0;
    int do_index = 0; 
    int go_flag = 1; 
    
    //在提示输入要操作的序号时,1表示插入,2表示删除,3表示对当前树三种遍历
    //4表示查找一个值是否存在
    
    //在插入或删除操作时,如果要输入一系列值,每个数字之间要以‘/’隔开
    //例如:4/5/6/7/8(回车),最后一个数字后直接回车,不要加斜杠
    
    
    
    
    while (go_flag){
    printf("请输入要进行的操作的序号:");
    scanf("%d", &do_index);

    switch (do_index) {
    case 1:{
    while (scanf("%d", &e.key)) {
        InsertAVL(T, e, ok_error);
        if (ok_error == OK) printf("成功插入%d\n",e.key);
        else printf("插入%d失败\n", e.key); 
        if('/' != getchar()) break;
            }
    break;        
     }
     case 2:{
    while (scanf("%d", &e.key)) {
        DeleteAVL(T, e, ok_error, can_end);
        if (ok_error == OK) printf("成功删除%d\n", e.key);
        else printf("删除%d失败\n",  e.key);
        can_end = FALSE;
        if('/' != getchar()) break;
            }
    break;        
      }
      case 3:{
    printf("inorder:");  
    Inorder(T);
    printf("\n");
    
    printf("preorder:");
    Preorder(T);
    printf("\n");
    
    printf("postorder:");
    Postorder(T);
    printf("\n");  
     
    break;    
      }                
    
      case 4:{              
     BBSTree T1;
     printf("请输入要查找的key值:");
     scanf("%d", &search_key);
     T1 = SearchBBST(T, search_key);  
     if(NULL != T1) printf("查找成功\n");
     else printf("查找失败\n");     
     break;
     }
    }
    printf("想继续这个程序吗(1 or 0):");
    scanf("%d", &go_flag);
     }
    DestroyBBST(T);    
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值