树平衡-C
我一直在尝试用C编写一个简单的AVL树实现。它也支持重复值。一切似乎都很好,但我时不时会得到一棵不平衡的树。对我来说,旋转函数似乎工作正常。我想身高检查有问题,但我似乎找不到问题 我刚从插入中得到的树是不平衡的,因此插入是有问题的。然后,在此之前,删除后的树通常是不平衡的。但有时它是适当平衡的,我似乎无法确定它是如何平衡的 此实现的代码如下所示:树平衡-C,c,tree,rotation,avl-tree,C,Tree,Rotation,Avl Tree,我一直在尝试用C编写一个简单的AVL树实现。它也支持重复值。一切似乎都很好,但我时不时会得到一棵不平衡的树。对我来说,旋转函数似乎工作正常。我想身高检查有问题,但我似乎找不到问题 我刚从插入中得到的树是不平衡的,因此插入是有问题的。然后,在此之前,删除后的树通常是不平衡的。但有时它是适当平衡的,我似乎无法确定它是如何平衡的 此实现的代码如下所示: #include <stdio.h> #include <stdlib.h> #include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <math.h>
#define SPACE_PER_NODE 2
#define MAX(x, y) (x) > (y) ? (x) : (y)
enum delete_flags {
DELETE_NO_FORCE,
DELETE_FORCE
};
typedef unsigned int uint;
struct tree_elem {
int data;
uint dup_count;
int height;
struct tree_elem* left;
struct tree_elem* right;
};
typedef struct tree_elem node;
node* create_bst();
void insert(node**, int);
void delete_elem(node**, int, uint);
node* search(node*, int);
node* get_parent(node*, node*);
node* find_min(node*);
node* get_successor(node*, node*);
uint max_depth(node*);
void display_helper(node*, int);
void display_tree(node*);
int get_height(node*);
void rotate_once_left(node**);
void rotate_once_right(node**);
void rotate_twice_left(node**);
void rotate_twice_right(node**);
void* s_malloc (const uint t) {
void* p = malloc(t);
if(!p) {
printf("Out of memory.\n");
exit(EXIT_FAILURE);
}
return p;
}
void s_free (void* p) {
if(!p) {
printf("Error: Tried to free NULL ptr.\n");
exit(EXIT_FAILURE);
}
else
free(p);
}
node* create_bst(int data) {
node* tree = (node*) s_malloc(sizeof(node));
tree->left = tree->right = NULL;
tree->data = data;
return tree;
}
void insert(node** t, int val) {
if(!(*t)) {
*t = (node*) s_malloc(sizeof(node));
(*t)->data = val;
(*t)->left = (*t)->right = NULL;
(*t)->dup_count = 0;
(*t)->height = 0;
return;
}
if((*t)->data < val) {
insert(&(*t)->right, val);
if(get_height((*t)->right) - get_height((*t)->left) >= 2) {
if((*t)->right->data < val)
rotate_once_right(&(*t));
else if((*t)->right->data > val)
rotate_twice_right(&(*t));
}
}
else if((*t)->data > val) {
insert(&(*t)->left, val);
if(get_height((*t)->left) - get_height((*t)->right) >= 2) {
if((*t)->left->data > val)
rotate_once_left(&(*t));
else if((*t)->left->data < val)
rotate_twice_left(&(*t));
}
}
else {
++(*t)->dup_count;
return; // this is important! if there are duplicates, they might cause an unwanted height change!
}
(*t)->height = MAX(get_height((*t)->left), get_height((*t)->right)) + 1;
}
node* get_successor(node* t, node* s) {
if(s->right)
return find_min(s->right);
node* suc = NULL;
node* temp = t;
// Start from root and search for successor in the tree
while (temp) {
if (s->data < temp->data) {
suc = temp;
temp = temp->left;
}
else if (s->data > temp->data)
temp = temp->right;
else
break;
}
return suc;
}
void free_tree (node* t) {
if (!t)
return;
free_tree(t->left);
free_tree(t->right);
free(t);
}
node* search(node* t, int val) {
if(!t)
return NULL;
if(t->data == val)
return t;
else if(t->data < val)
return search(t->right, val);
return search(t->left, val);
}
node* find_min(node* t) {
node* temp = t;
while(temp->left)
temp = temp->left;
return temp;
}
uint max_depth(node* t) {
if (!t)
return 0;
int ldepth = max_depth(t->left);
int rdepth = max_depth(t->right);
if (ldepth > rdepth)
return ldepth + 1;
return rdepth + 1;
}
void display_helper(node* t, int spaces) {
int width = ceil(log10(max_depth(t)+0.01)) + 2;
wchar_t* sp64 = L" ";
if (!t) {
wprintf(L"\n");
return;
}
display_helper(t->right, spaces + width);
wprintf(L"%*.*s%d\n", 0, spaces, sp64, t->data);
display_helper(t->left, spaces + width);
}
void display_tree(node* t) {
if(t)
display_helper(t, SPACE_PER_NODE);
}
int get_height(node* t) {
if(!t)
return 0;
return t->height;
}
void rotate_once_left(node** k1) {
node* temp = (*k1)->left;
(*k1)->left = temp->right;
temp->right = *k1;
(*k1)->height = MAX(get_height((*k1)->left), get_height((*k1)->right)) + 1;
temp->height = MAX(get_height(temp->left), (*k1)->height) + 1;
*k1 = temp;
}
void rotate_once_right(node** k1) {
node* temp = (*k1)->right;
(*k1)->right = temp->left;
temp->left = *k1;
(*k1)->height = MAX(get_height((*k1)->left), get_height((*k1)->right)) + 1;
temp->height = MAX(get_height(temp->right), (*k1)->height) + 1;
*k1 = temp;
}
void rotate_twice_left(node** k1) {
rotate_once_right(&(*k1)->left);
rotate_once_left(k1);
}
void rotate_twice_right(node** k1) {
rotate_once_left(&(*k1)->right);
rotate_once_right(k1);
}
int main() {
srand(time(NULL));
node* tree = create_bst(rand() % 15 + 1);
for(uint i = 0; i < 14; ++i) {
int elem;
// create unique elements from 1 to 20.
do {
elem = rand() % 15 + 1;
} while (search(tree, elem));
insert(&tree, elem);
}
display_tree(tree);
int input;
do {
printf("Enter value to delete: ");
scanf("%d", &input);
delete_elem(&tree, input, DELETE_NO_FORCE);
display_tree(tree);
} while(input != -1);
return 0;
}
#包括
#包括
#包括
#包括
#包括
#为每个节点2定义空间
#定义最大值(x,y)(x)>(y)?(x) :(y)
枚举删除\u标志{
删除(无)力,,
删除强制力
};
typedef无符号整数单元;
结构树元素{
int数据;
单位重复计数;
内部高度;
结构树元素*左;
结构树元素*右;
};
typedef结构树元素节点;
节点*create_bst();
无效插入(节点**,int);
void delete_elem(节点**,int,uint);
节点*搜索(节点*,int);
节点*获取父节点(节点*,节点*);
节点*查找_min(节点*);
节点*获取后续节点(节点*,节点*);
uint最大深度(节点*);
无效显示辅助对象(节点*,int);
无效显示树(节点*);
int get_高度(节点*);
无效向左旋转一次(节点**);
无效向右旋转一次(节点**);
无效向左旋转两次(节点**);
void向右旋转两次(节点**);
void*s_malloc(施工){
void*p=malloc(t);
如果(!p){
printf(“内存不足。\n”);
退出(退出失败);
}
返回p;
}
无效s_自由(无效*p){
如果(!p){
printf(“错误:试图释放空ptr。\n”);
退出(退出失败);
}
其他的
自由基(p);
}
节点*创建(整型数据){
node*tree=(node*)s_malloc(sizeof(node));
树->左=树->右=空;
树->数据=数据;
回归树;
}
无效插入(节点**t,int val){
如果(!(*t)){
*t=(node*)s_malloc(sizeof(node));
(*t)->数据=val;
(*t)->左=(*t)->右=空;
(*t)->dup_计数=0;
(*t)->高度=0;
返回;
}
如果((*t)->数据右侧,val);
如果(获取_高度((*t)->右侧)-获取_高度((*t)->左侧)>=2){
如果((*t)->右->数据右->数据>val)
向右旋转两次(&(*t));
}
}
else if((*t)->data>val){
插入(&(*t)->左侧,val);
如果(获取_高度((*t)->左)-获取_高度((*t)->右)>=2){
如果((*t)->左->数据>val)
向左旋转一次(&(*t));
如果((*t)->左->数据重复计数;
return;//这很重要!如果存在重复项,可能会导致不必要的高度更改!
}
(*t)->高度=最大值(获取高度((*t)->左侧),获取高度((*t)->右侧))+1;
}
节点*获取后续节点(节点*t,节点*s){
如果(s->右侧)
返回find_min(s->right);
node*suc=NULL;
节点*temp=t;
//从根目录开始,在树中搜索后续目录
while(临时){
如果(s->datadata){
suc=温度;
温度=温度->左侧;
}
否则,如果(s->data->temp->data)
温度=温度->右侧;
其他的
打破
}
返回suc;
}
无空_树(节点*t){
如果(!t)
返回;
自由树(t->左);
自由树(t->右);
自由(t);
}
节点*搜索(节点*t,int val){
如果(!t)
返回NULL;
如果(t->data==val)
返回t;
else if(t->data右,val);
返回搜索(t->左,val);
}
节点*find_min(节点*t){
节点*temp=t;
while(临时->左)
温度=温度->左侧;
返回温度;
}
uint最大深度(节点*t){
如果(!t)
返回0;
int ldepth=最大深度(t->左);
int rdepth=最大深度(t->右侧);
如果(ldepth>rdepth)
返回ldepth+1;
返回rdepth+1;
}
无效显示辅助对象(节点*t,整数空间){
内部宽度=天花板(log10(最大深度(t)+0.01))+2;
wchar_t*sp64=L”“;
如果(!t){
wprintf(L“\n”);
返回;
}
显示辅助对象(t->右侧,空格+宽度);
wprintf(L“%*.*s%d\n”,0,空格,sp64,t->data);
显示辅助对象(t->左,空格+宽度);
}
无效显示树(节点*t){
if(t)
显示辅助对象(t,每个节点的空间);
}
int get_高度(节点*t){
如果(!t)
返回0;
返回t->高度;
}
无效向左旋转一次(节点**k1){
节点*temp=(*k1)->左侧;
(*k1)->左=温度->右;
温度->右侧=*k1;
(*k1)->高度=最大值(获取高度(*k1)->左侧),获取高度((*k1)->右侧))+1;
温度->高度=最大值(获取高度(温度->左侧),(*k1)->高度)+1;
*k1=温度;
}
无效向右旋转一次(节点**k1){
节点*temp=(*k1)->右侧;
(*k1)->右=温度->左;
温度->左=*k1;
(*k1)->高度=最大值(获取高度(*k1)->左侧),获取高度((*k1)->右侧))+1;
温度->高度=最大值(获取高度(温度->右侧),(*k1)->高度)+1;
*k1=温度;
}
无效向左旋转两次(节点**k1){
向右旋转一次(&(*k1)->向左);
向左旋转一次(k1);
}
无效向右旋转两次(节点**k1){
向左旋转一次(&(*k1)->向右);
向右旋转一次(k1);
}
int main(){
srand(时间(空));
node*tree=create_bst(rand()%15+1);
对于(uint i=0;i<14;++i){
内因;
//创建从1到20的唯一元素。
做{
elem=rand()%15+1;
}while(搜索(树、元素));
插入(&树,元素);
}
显示_树(tree);
int输入;
做{
printf(“输入要删除的值:”);
scanf(“%d”,输入(&I));
删除元素(树,输入,删除不强制);
D
MAX(get_height((*t)->left), get_height((*t)->right)) + 1;
(get_height((*t)->left)) > (get_height((*t)->right))
? (get_height((*t)->left))
: (get_height((*t)->right)) + 1;