zoukankan      html  css  js  c++  java
  • 【c语言】【每周一练】平衡二叉树

         平衡二叉树是这样一棵树:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。查找、插入和删除在平均和最坏情况下都是O(log n)。可以用于数据库设计,内存分配算法等。

        

    /*
    平衡二叉查找树
    written by huals
    2012.10.13
    */
    #include <stdio.h>
    #include <stdlib.h>
    typedef struct BSTreeNode{
    int value;
    struct BSTreeNode *left;
    struct BSTreeNode *right;
    struct BSTreeNode *parent;
    //到叶子节点最长路径(本节点不算)
    int len;
    } BSTreeNode;
    typedef struct BSTree{
    BSTreeNode *root;
    int node_number;
    
    } BSTree;
    
    void BSTree_init(BSTree *tree);
    void BSTreeNode_init(BSTreeNode *z,int value);
    void Insert_BSTree(BSTree *T,BSTreeNode *z);
    void Left_rotate(BSTree *T,BSTreeNode *z);
    void Right_rotate(BSTree *T,BSTreeNode *z);
    void Delete_node(BSTree *T,BSTreeNode *z);
    BSTreeNode* Next_node(BSTree *T,BSTreeNode *z);
    BSTreeNode* Pre_node(BSTree *T,BSTreeNode *z);
    BSTreeNode* Search_node(BSTree *T,int value);
    void Modify_len(BSTree *T,BSTreeNode *x);
    void Balance_tree(BSTree *T,BSTreeNode *y);
    void Print_tree(BSTree *T);
    void Print_value(BSTreeNode *z);
    void Print_info_tree(BSTree *T);
    
    int main(void){
    BSTree *tree;
    int i,j;
    tree=(BSTree *)malloc(sizeof(BSTree));
    BSTree_init(tree);
    BSTreeNode *node=NULL;
    for(j=1;j<=10;j++){
    node=(BSTreeNode *)malloc(sizeof(BSTreeNode));
    BSTreeNode_init(node,j);
    Insert_BSTree(tree,node);
    
    Print_tree(tree);
    }
    //删除第十个节点,输出
    //Delete_node(tree,Search_node(tree,4));
    Print_info_tree(tree);
    Print_tree(tree);
    }
    //树初始化
    void BSTree_init(BSTree *tree){
    tree->root=NULL;
    tree->node_number=0;
    }
    //节点初始化
    void BSTreeNode_init(BSTreeNode *z,int value){
    z->value=value;
    z->parent=NULL;
    z->left=NULL;
    z->right=NULL;
    z->len=0;
    }
    //插入节点,ok
    void Insert_BSTree(BSTree *T,BSTreeNode *z){
    BSTreeNode *y=T->root;BSTreeNode *x=NULL;
    int llen,rlen,flag;
    while(y!=NULL){
    x=y;
    if(z->value<=y->value)
    y=y->left;
    else
    y=y->right;
    }
    z->parent=x;
    if(x==NULL)
    T->root=z;
    else{
    if(z->value<=x->value)
    x->left=z;
    else
    x->right=z;
    }
    //更新插入节点到根节点的len值
    y=z;
    while(y->parent!=NULL && y->len+1>y->parent->len){
    y->parent->len=y->len+1;
    y=y->parent;
    }
    //调整二叉树使平衡
    Balance_tree(T,z);
    T->node_number++;
    }
    //左旋
    void Left_rotate(BSTree *T,BSTreeNode *z){
    BSTreeNode *x=z->right;
    int llen,rlen;
    z->right=x->left;
    if(x->left!=NULL)
    (x->left)->parent=z;
    x->parent=z->parent;
    if(z->parent==NULL)
    T->root=x;
    else{
    if((z->parent)->right==z)
    (z->parent)->right=x;
    else
    (z->parent)->left=x;
    }
    z->parent=x;
    x->left=z;
    //手动更新调整变换的关键点的len
    llen=(z->left==NULL?0:z->left->len+1);
    rlen=(z->right==NULL?0:z->right->len+1);
    z->len=(llen>=rlen?llen:rlen);
    llen=z->len+1;
    rlen=(x->right==NULL?0:x->right->len+1);
    x->len=(llen>=rlen?llen:rlen);
    //调试用:输出调整节点的值
    //printf("z is %d,z len is %d\n",z->value,z->len);
    //更新因旋转后造成len的变化
    Modify_len(T,x);
    }
    //右旋
    void Right_rotate(BSTree *T,BSTreeNode *z){
    BSTreeNode *x=z->left;
    int llen,rlen;
    z->left=x->right;
    if(x->right!=NULL)
    x->right->parent=z;
    x->parent=z->parent;
    if(z->parent==NULL)
    T->root=x;
    else{
    if(z->parent->left==z)
    z->parent->left=x;
    else
    z->parent->right=x;
    }
    x->right=z;
    z->parent=x;
    //更新len
    llen=(z->left==NULL?0:z->left->len);
    rlen=(z->right==NULL?0:z->right->len);
    z->len=(llen>=rlen?llen+1:rlen+1);
    llen=z->len+1;
    rlen=(x->left==NULL?0:x->left->len+1);
    x->len=(llen>=rlen?llen:rlen);
    Modify_len(T,z);
    }
    //搜索后继节点
    BSTreeNode* Next_node(BSTree *T,BSTreeNode *z){
    BSTreeNode *y=NULL;
    BSTreeNode *x=z->right;
    while(x!=NULL){
    y=x;
    x=x->left;
    }
    if(y==NULL){
    x=z;
    while(x->parent!=NULL &&(x->parent)->right==x)
    x=x->parent;
    y=x->parent;
    }
    return y;
    }
    //搜索前仆节点
    BSTreeNode* Pre_node(BSTree *T,BSTreeNode *z){
    BSTreeNode *y=NULL;
    BSTreeNode *x=z->left;
    while(x!=NULL){
    y=x;
    x=x->right;
    }
    if(y==NULL){
    x=z;
    while(x->parent!=NULL && (x->parent)->left==x)
    x=x->parent;
    y=x->parent;
    }
    return y;
    }
    //搜索指定关键字节点,返回节点指针
    BSTreeNode* Search_node(BSTree *T,int value){
    BSTreeNode *x=T->root;
    while(x!=NULL){
    if(value==x->value)
    return x;
    else if(value<x->value)
    x=x->left;
    else
    x=x->right;
    }
    return x;
    }
    //输出树的节点及其len值
    void Print_tree(BSTree *T){
    BSTreeNode *root=T->root;
    if(root==NULL)
    printf("The tree is NULL.\n");
    else
    Print_value(root);
    }
    //输出树的信息:根节点及节点数目
    void Print_info_tree(BSTree *T){
    BSTreeNode *root=T->root;
    if(root==NULL)
    printf("The tree is NULL.\n");
    else
    printf("the root node is %d, node number is %d\n",root->value,T->node_number);
    }
    //递归输出节点值及len值
    void Print_value(BSTreeNode *z){
    if(z->left!=NULL)
    Print_value(z->left);
    printf("value:%d len:%d\n",z->value,z->len);
    if(z->right!=NULL)
    Print_value(z->right);
    }
    //删除节点
    void Delete_node(BSTree *T,BSTreeNode *z){
    BSTreeNode *x,*y;
    int llen,rlen;
    x=NULL;y=NULL;
    if(z->left==NULL || z->right==NULL)
    y=z;
    else
    y=Next_node(T,z);
    if(y->left!=NULL)
    x=y->left;
    else
    x=y->right;
    if(x!=NULL)
    x->parent=y->parent;
    if(y->parent==NULL)
    T->root=x;
    else{
    if(y->parent->left==y)
    y->parent->left=x;
    else
    y->parent->right=x;
    }
    if(y!=z){
    z->value=y->value;
    //z->len=y->len;
    }
    x=y->parent;
    if(x!=NULL){
    llen=(x->left==NULL?0:x->left->len+1);
    rlen=(x->right==NULL?0:x->right->len+1);
    x->len=(llen>=rlen?llen:rlen);
    Modify_len(T,x);
    Balance_tree(T,x);
    T->node_number--;
    }
    }
    /*
    旋转节点和删除节点时会造成节点len值动荡,而x则是动荡的那一支,x本身len值正确,只是x父节点,祖先节点未知,需要调整
    ok
    */
    void Modify_len(BSTree *T,BSTreeNode *x){
    int llen,rlen;
    BSTreeNode *z;
    llen=x->len+1;
    if(x->parent==NULL)
    return;
    z=(x->parent->left==x?x->parent->right:x->parent->left);
    rlen=(z==NULL?0:z->len+1);
    while(x->parent->len!=rlen){
    x->parent->len=llen;
    x=x->parent;
    if(x->parent==NULL)
    return;
    llen=x->len+1;
    z=(x->parent->left==x?x->parent->right:x->parent->left);
    rlen=(z==NULL?0:z->len+1);
    }
    }
    //沿着y想根节点方向搜索不平衡节点,并通过旋转调整
    void Balance_tree(BSTree *T,BSTreeNode *y){
    int flag=0;
    int llen,rlen;
    BSTreeNode *x=NULL;
    while(y!=NULL && !flag){
    llen=(y->left==NULL?0:(y->left)->len+1);
    rlen=(y->right==NULL?0:(y->right)->len+1);
    //判断是左旋还是右旋
    switch(llen-rlen){
    case 2:flag=1;break;
    case -2:flag=2;break;
    default :flag=0;break;
    }
    y=y->parent;
    }
    //旋转时需要判断是否需要两次旋转
    if(flag==1){
    if(y==NULL)
    y=T->root;
    else
    y=y->left;
    x=y->left;
    llen=(x->left==NULL?0:(x->left)->len+1);
    rlen=(x->right==NULL?0:(x->right)->len+1);
    if(llen>rlen)
    Right_rotate(T,y);
    else{
    Left_rotate(T,x);
    Right_rotate(T,y);
    }
    }
    if(flag==2){
    if(y==NULL)
    y=T->root;
    else
    y=y->right;
    x=y->right;
    llen=(x->left==NULL?0:(x->left)->len+1);
    rlen=(x->right==NULL?0:(x->right)->len+1);
    if(rlen>llen){
    Left_rotate(T,y);
    }
    else{
    Right_rotate(T,x);
    Left_rotate(T,y);
    }
    }
    }
  • 相关阅读:
    Space for commit to queue couldn't be acquired
    数据埋点(浅谈埋点方式与上报收集)
    Hashed Indexes Geospatial Index
    线程安全 对StringBuilder抛出ArrayIndexOutOfBoundsException的探究
    [a,s]=[22,3]
    Flume-ng-sdk源码分析
    pstree
    将线上服务器生成的日志信息实时导入kafka,采用agent和collector分层传输,app的数据通过thrift传给agent,agent通过avro sink将数据发给collector,collector将数据汇集后,发送给kafka
    线程池 最大线程数
    es 300G 数据删除 执行计划 curl REST 操作
  • 原文地址:https://www.cnblogs.com/huals/p/2722670.html
Copyright © 2011-2022 走看看