14 C语言实现平衡二叉树

//LL型失衡 右旋
//RR型失衡 左旋
//RL型失衡 先右旋 再左旋
//LR型失衡 先左旋 再右旋
#include "stdio.h"
#include "stdlib.h"

typedef int ElemType;
typedef struct node {
    ElemType data;
    int height;
    struct node *left;
    struct node *right;
} Node;

Node *create_node(ElemType value) {
    Node *node = (Node *) malloc(sizeof(Node));
    if (node == NULL) {
        exit(-1);
    }

    node->data = value;
    node->height = 1;
    node->left = NULL;
    node->right = NULL;
    return node;
}

//获取树的高度
int getHeight(Node *node) {
    if (node == NULL) {
        return 0;
    }

    return node->height;
}

int max(int a, int b) {
    return a > b ? a : b;
}

int getTreeHeight(Node *node) {
    if (node == NULL) {
        return 0;
    }

    return max(getTreeHeight(node->left), getTreeHeight(node->right)) + 1;
}

//左旋转
Node *leftRotate(Node *root) {
    Node *newroot = root->right;//当前结点的右子节点作为新的树根
    root->right = newroot->left;//将新树根的左子树作为原根的右子树
    newroot->left = root;//将原根作为新根的左子树

    root->height = 1 + max(getHeight(root->left), getHeight(root->right));
    newroot->height = 1 + max(getHeight(newroot->left), getHeight(newroot->right));
    return newroot;
}

//右旋转
Node *rightRotate(Node *root) {
    Node *newroot = root->left;//当前结点的左节点作为新的树根
    root->left = newroot->right;//将新节点右边的子树作为原根结点的左子树
    newroot->right = root;//新节点的右子树为原根结点

    root->height = 1 + max(getHeight(root->left), getHeight(root->right));
    newroot->height = 1 + max(getHeight(newroot->left), getHeight(newroot->right));
    return newroot;
}

//获取平衡因子
int getBalance(Node *node) {
    return getHeight(node->left) - getHeight(node->right);
}

//插入
Node *insert_node(Node *node, ElemType value) {
    if (node == NULL) {
        return create_node(value);
    }

    if (node->data > value) {
        node->left = insert_node(node->left, value);
    } else if (node->data < value) {
        node->right = insert_node(node->right, value);
    } else {
        return node;
    }

    //更新树高
    node->height = 1 + max(getHeight(node->left), getHeight(node->right));

    // 获取平衡因子
    int balance = getBalance(node);
    //LL型失衡
    if (balance > 1 && getBalance(node->left) > 0) {
        return rightRotate(node);
    }
    //LR型失衡
    if (balance > 1 && getBalance(node->left) < 0) {
        node->left = leftRotate(node->left);
        return rightRotate(node);
    }
    //RR型失衡
    if (balance < -1 && getBalance(node->right) < 0) {
        return leftRotate(node);
    }
    //RL型失衡
    if (balance < -1 && getBalance(node->right) > 0) {
        node->right = rightRotate(node->right);
        return leftRotate(node);
    }

    return node;
}

void preOrder(Node *node) {
    if (node == NULL) {
        return;
    }

    printf("%d ", node->data);
    preOrder(node->left);
    preOrder(node->right);
}

void inOrder(Node *node) {
    if (node == NULL) {
        return;
    }

    inOrder(node->left);
    printf("%d ", node->data);
    inOrder(node->right);
}

Node *find(Node *node, ElemType value, int *counter) {
    Node *current = node;
    while (current != NULL) {
        if (current->data > value) {
            current = current->left;
            (*counter)++;
        } else if (current->data < value) {
            current = current->right;
            (*counter)++;
        } else {
            (*counter)++;
            return current;
        }
    }

    return NULL;
}

//删除节点恢复平衡
/*
 * 前半部分 二叉搜索树的删除
 * 后半部分 插入节点导致失衡的修改,稍作调整
 * */
Node *delete_node(Node *node, int value) {
    if (node == NULL) {
        return NULL;
    }

    if (node->data > value) {
        node->left = delete_node(node->left, value);
    } else if (node->data < value) {
        node->right = delete_node(node->right, value);
    } else if (node->data == value) {
        //情况一 要删除的节点就是叶子结点
        if (node->left == NULL && node->right == NULL) {
            Node *temp = node;
            node = NULL;
            free(temp);
        } else if (node->left == NULL && node->right != NULL) {
            //情况二 只有一个方向有节点 直接用有节点的数据进行替换就可以了
            Node *temp = node;
            node = node->right;
            free(temp);
        } else if (node->left != NULL && node->right == NULL) {
            //情况二 只有一个方向有节点
            Node *temp = node;
            node = node->left;
            free(temp);
        } else if (node->left != NULL && node->right != NULL) {
            //情况三 要删除的节点有左孩子也有右孩子
            Node *current = node->right;
            while (current->left != NULL) {
                current = current->left;
            }
            node->data = current->data;
            node->right = delete_node(node->right, current->data);
        }
    }

    //删除完成 下面开始调整
    if (node == NULL) {
        return node;
    }

    //更新树高
    node->height = 1 + max(getHeight(node->left), getHeight(node->right));

    // 获取平衡因子
    int balance = getBalance(node);
    //LL型失衡
    if (balance > 1 && getBalance(node->left) >= 0) {
        return rightRotate(node);
    }
    //LR型失衡
    if (balance > 1 && getBalance(node->left) < 0) {
        node->left = leftRotate(node->left);
        return rightRotate(node);
    }
    //RR型失衡
    if (balance < -1 && getBalance(node->right) <= 0) {
        return leftRotate(node);
    }
    //RL型失衡
    if (balance < -1 && getBalance(node->right) > 0) {
        node->right = rightRotate(node->right);
        return leftRotate(node);
    }

    return node;
}

void test() {
    Node *root = insert_node(NULL, 1);
    root = insert_node(root, 2);
    root = insert_node(root, 3);
    root = insert_node(root, 4);
    root = insert_node(root, 5);
    root = insert_node(root, 6);
    root = insert_node(root, 7);
    root = insert_node(root, 8);
    root = insert_node(root, 9);
    root = insert_node(root, 10);

    int counter = 0;
    Node *result = find(root, 6, &counter);
    if (result) {
        printf("找了%d次", counter);
    }

    printf("\n前序遍历\n");
    preOrder(root);
    printf("\n中序遍历\n");
    inOrder(root);

//    root = delete_node(root, 1);
//    root = delete_node(root, 2);
//    root = delete_node(root, 7);

//    printf("\n前序遍历\n");
//    preOrder(root);
//    printf("\n中序遍历\n");
//    inOrder(root);

    printf("\n树高为%d", getTreeHeight(root));
}

int main() {
    test();
    return 0;
}

运行效果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值