【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);
}
}
}

 

转载于:https://www.cnblogs.com/huals/archive/2012/10/13/2722670.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是用C语言实现的平衡二叉树代码: ```c #include <stdio.h> #include <stdlib.h> typedef struct node { int data; int height; struct node *left, *right; } Node; // 获取节点高度 int height(Node *n) { if (n == NULL) return 0; return n->height; } // 获取最大值 int max(int a, int b) { return (a > b) ? a : b; } // 创建节点 Node* newNode(int data) { Node* node = (Node*) malloc(sizeof(Node)); node->data = data; node->left = NULL; node->right = NULL; node->height = 1; return node; } // 右旋 Node* rightRotate(Node *y) { Node *x = y->left; Node *T2 = x->right; x->right = y; y->left = T2; y->height = max(height(y->left), height(y->right)) + 1; x->height = max(height(x->left), height(x->right)) + 1; return x; } // 左旋 Node* leftRotate(Node *x) { Node *y = x->right; Node *T2 = y->left; y->left = x; x->right = T2; x->height = max(height(x->left), height(x->right)) + 1; y->height = max(height(y->left), height(y->right)) + 1; return y; } // 获取平衡因子 int getBalance(Node *n) { if (n == NULL) return 0; return height(n->left) - height(n->right); } // 插入节点 Node* insert(Node* node, int data) { if (node == NULL) return newNode(data); if (data < node->data) { node->left = insert(node->left, data); } else if (data > node->data) { node->right = insert(node->right, data); } else { return node; } node->height = 1 + max(height(node->left), height(node->right)); int balance = getBalance(node); // 左左情况 if (balance > 1 && data < node->left->data) { return rightRotate(node); } // 右右情况 if (balance < -1 && data > node->right->data) { return leftRotate(node); } // 左右情况 if (balance > 1 && data > node->left->data) { node->left = leftRotate(node->left); return rightRotate(node); } // 右左情况 if (balance < -1 && data < node->right->data) { node->right = rightRotate(node->right); return leftRotate(node); } return node; } // 中序遍历 void inorder(Node *root) { if (root != NULL) { inorder(root->left); printf("%d ", root->data); inorder(root->right); } } int main() { Node *root = NULL; root = insert(root, 10); root = insert(root, 20); root = insert(root, 30); root = insert(root, 40); root = insert(root, 50); root = insert(root, 25); printf("中序遍历:"); inorder(root); printf("\n"); return 0; } ``` 该代码中实现了平衡二叉树的插入操作和中序遍历操作,可以通过插入操作来构建平衡二叉树,并通过中序遍历操作来验证平衡二叉树的正确性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值