树平衡-C

树平衡-C,c,tree,rotation,avl-tree,C,Tree,Rotation,Avl Tree,我一直在尝试用C编写一个简单的AVL树实现。它也支持重复值。一切似乎都很好,但我时不时会得到一棵不平衡的树。对我来说,旋转函数似乎工作正常。我想身高检查有问题,但我似乎找不到问题 我刚从插入中得到的树是不平衡的,因此插入是有问题的。然后,在此之前,删除后的树通常是不平衡的。但有时它是适当平衡的,我似乎无法确定它是如何平衡的 此实现的代码如下所示: #include <stdio.h> #include <stdlib.h> #include <string.h>

我一直在尝试用C编写一个简单的AVL树实现。它也支持重复值。一切似乎都很好,但我时不时会得到一棵不平衡的树。对我来说,旋转函数似乎工作正常。我想身高检查有问题,但我似乎找不到问题

我刚从插入中得到的树是不平衡的,因此插入是有问题的。然后,在此之前,删除后的树通常是不平衡的。但有时它是适当平衡的,我似乎无法确定它是如何平衡的

此实现的代码如下所示:

#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;