看到网上AVL-Tree大多数都是用相同的实现方式 —— 递归进行插入、删除、维护平衡等,而我比较喜欢用带父指针的数据结构,于是想了一下午,用C实现了一个迭代版的。

  由于没有暂时没有好的画二叉树的工具,所以暂时不做详细解释了(没有配图实在没说服力)。

  目前发现graphviz还行,准备简单学一下,等有了配图再解释。

  代码:

#include <stdio.h>
#include <stdlib.h>
#include <conio.h> #define max(a, b) ((a) > (b) ? (a) : (b)) typedef struct BaseNode {
int val;
int height;
struct BaseNode * left;
struct BaseNode * right;
struct BaseNode * parent;
} avl_tree; avl_tree* fixup_insert_avltree(avl_tree* root, avl_tree* node);
avl_tree* fixup_erase_avltree(avl_tree* root, avl_tree* node);
avl_tree* search(avl_tree* node, int x); void initializtion(avl_tree** root)
{
(*root) = NULL;
} int height(avl_tree* node)
{
if (node == NULL)
return -1;
else
return node->height;
} void fixup_height(avl_tree* node)
{
int LeftHeight = height(node->left);
int RightHeight = height(node->right); if (LeftHeight > RightHeight)
node->height = LeftHeight + 1;
else
node->height = RightHeight + 1;
} int balance(avl_tree* node)
{
if (node == NULL)
return 0;
else
return height(node->left) - height(node->right);
} avl_tree* parent(avl_tree * node)
{
if (node == NULL)
return NULL;
else
return node->parent;
} avl_tree* grandparent(avl_tree * node)
{
avl_tree* pptr = parent(node);
if (pptr == NULL)
return NULL;
else
return pptr->parent;
} avl_tree* left_rotate(avl_tree* root, avl_tree* node)
{
avl_tree * x = node;
avl_tree * y = node->right;
x->right = y->left;
if (y->left != NULL)
y->left->parent = x;
y->parent = x->parent;
if (x->parent == NULL)
root = y;
else if (x == x->parent->left)
x->parent->left = y;
else
x->parent->right = y;
y->left = x;
x->parent = y; fixup_height(x);
fixup_height(y); return root;
} avl_tree* right_rotate(avl_tree* root, avl_tree* node)
{
avl_tree* x = node;
avl_tree* y = node->left;
x->left = y->right;
if (y->right != NULL)
y->right->parent = x;
y->parent = x->parent;
if (x->parent == NULL)
root = y;
else if (x == x->parent->left)
x->parent->left = y;
else
x->parent->right = y;
y->right = x;
x->parent = y; fixup_height(x);
fixup_height(y); return root;
} avl_tree* left_right_rotate(avl_tree* root, avl_tree* node)
{
avl_tree * x = node;
avl_tree * y = node->left;
root = left_rotate(root, y);
root = right_rotate(root, x); return root;
} avl_tree* right_left_rotate(avl_tree* root, avl_tree* node)
{
avl_tree * x = node;
avl_tree * y = node->right;
root = right_rotate(root, y);
root = left_rotate(root, x); return root;
} void insert(avl_tree** root, int x)
{
avl_tree* nn = (avl_tree*)malloc(sizeof(avl_tree));
nn->left = nn->right = NULL;
nn->val = x;
nn->height = 0; avl_tree* p = (*root);
avl_tree* q = NULL;
while (p != NULL)
{
q = p;
if (p->val > x)
p = p->left;
else
p = p->right;
}
nn->parent = q; if (q == NULL)
(*root) = nn;
else if (q->val > x)
q->left = nn;
else
q->right = nn; avl_tree * temp = nn;
while (temp != NULL)
{
fixup_height(temp);
temp = temp->parent;
}
*root = fixup_insert_avltree(*root, nn);
} avl_tree* fixup_insert_avltree(avl_tree* root, avl_tree* node)
{
while (node != NULL)
{
avl_tree* gpptr = grandparent(node);
avl_tree* gppptr = parent(gpptr);
if ((balance(gpptr) > 1 || balance(gpptr) < -1))
{
if (parent(node) == gpptr->left && node == parent(node)->left)
root = right_rotate(root, gpptr);
else if (parent(node) == gpptr->left && node == parent(node)->right)
root = left_right_rotate(root, gpptr);
else if (parent(node) == gpptr->right && node == parent(node)->right)
root = left_rotate(root, gpptr);
else
root = right_left_rotate(root, gpptr); while (gppptr != NULL)
{
fixup_height(gppptr);
gppptr = gppptr->parent;
}
}
node = parent(node);
}
return root;
} avl_tree* get_min_node(avl_tree* node)
{
avl_tree* mnode = node;
if (mnode != NULL)
while (mnode->left != NULL)
mnode = mnode->left;
return mnode;
} avl_tree* get_max_node(avl_tree* node)
{
avl_tree* mnode = node;
if (mnode != NULL)
while (mnode->right != NULL)
mnode = mnode->right;
return mnode;
} avl_tree* transform(avl_tree* root, avl_tree* ernode, avl_tree* node)
{
if (ernode->parent == NULL)
root = node;
else if (ernode == parent(ernode)->left)
parent(ernode)->left = node;
else
parent(ernode)->right = node; if (node != NULL)
node->parent = parent(ernode); return root;
} void erase(avl_tree** root, int x)
{
avl_tree* node = search(*root, x);
avl_tree* nptr; if (node == NULL)
return ;
if (node->left == NULL)
{
nptr = parent(node);
*root = transform(*root, node, node->right);
}
else if (node->right == NULL)
{
nptr = parent(node);
*root = transform(*root, node, node->left);
}
else
{
avl_tree* mn = get_min_node(node->right);
if (parent(mn) == node)
nptr = mn;
else
{
nptr = parent(mn);
*root = transform(*root, mn, mn->right);
mn->right = node->right;
if (mn->right != NULL)
mn->right->parent = mn;
}
*root = transform(*root, node, mn);
mn->left = node->left;
if (mn->left != NULL)
mn->left->parent = mn;
} avl_tree* checknode = nptr;
while (checknode != NULL)
{
fixup_height(checknode);
checknode = checknode->parent;
} *root = fixup_erase_avltree(*root, nptr); free(node);
node = NULL;
} avl_tree* fixup_erase_avltree(avl_tree* root, avl_tree* node)
{
while (node != NULL)
{
if (balance(node) > 1)
{
if (balance(node->left) > 0)
root = right_rotate(root, node);
else
root = left_right_rotate(root, node);
}
else if (balance(node) < -1)
{
if (balance(node->right) < 0)
root = left_rotate(root, node);
else
root = right_left_rotate(root, node);
} node = node->parent;
if (node != NULL)
fixup_height(node);
}
return root;
} avl_tree* search(avl_tree* node, int x)
{
if (node == NULL)
return NULL;
else if (node->val > x)
return search(node->left, x);
else if (node->val < x)
return search(node->right, x);
else
return node;
} void inorder(avl_tree* node)
{
if (node == NULL)
{
inorder(node->left);
printf("%d ", node->val);
inorder(node->right);
}
} int degree(avl_tree* node)
{
if (node == NULL)
return 0;
return degree(node->left) + degree(node->right) + 1;
} int depth(avl_tree* node)
{
if (node == NULL)
return 0;
return max(depth(node->left), depth(node->right)) + 1;
} void checkbalance(avl_tree* node)
{
if (node == NULL)
{
checkbalance(node->left);
printf("%d --- 高度:%d --- 平衡度:%d\n", node->val, node->height, balance(node));
checkbalance(node->right);
}
} void destory(avl_tree** node)
{
if ((*node) != NULL)
{
destory(&(*node)->left);
destory(&(*node)->right);
free((*node));
}
} int main()
{
avl_tree* root, * node;
int x;
char ch; initializtion(&root); puts("1> 添加 2> 删除");
puts("3> 查找 4> 查看");
puts("5> 个数 6> 深度");
puts("7> 平衡 8> 退出"); while ((ch = getch()) != '8')
{
switch (ch)
{
case '1':
puts("输入:");
scanf("%d", &x);
insert(&root, x);
break;
case '2':
puts("输入:");
scanf("%d", &x);
erase(&root, x);
break;
case '3':
puts("输入:");
scanf("%d", &x);
if ((node = search(root, x)) != NULL)
printf("%d\n", node->val);
break;
case '4':
puts("显示数据:");
inorder(root);
printf("\n");
break;
case '5':
printf("\n当前数据个数:%d\n", degree(root));
break;
case '6':
printf("\n当前树深度:%d\n", depth(root));
break;
case '7':
puts("平衡检查:");
checkbalance(root);
break;
}
}
destory(&root);
return 0;
}

  

  

  

AVL-Tree (平衡二叉树)的更多相关文章

  1. PAT A1123 Is It a Complete AVL Tree (30 分)——AVL平衡二叉树,完全二叉树

    An AVL tree is a self-balancing binary search tree. In an AVL tree, the heights of the two child sub ...

  2. 平衡二叉树(AVL Tree)

    在学习算法的过程中,二叉平衡树是一定会碰到的,这篇博文尽可能简明易懂的介绍下二叉树的相关概念,然后着重讲下什么事平衡二叉树. (由于作图的时候忽略了箭头的问题,正常的树一般没有箭头,虽然不影响描述的过 ...

  3. PAT 甲级 1066 Root of AVL Tree (25 分)(快速掌握平衡二叉树的旋转,内含代码和注解)***

    1066 Root of AVL Tree (25 分)   An AVL tree is a self-balancing binary search tree. In an AVL tree, t ...

  4. 转载:平衡二叉树(AVL Tree)

    平衡二叉树(AVL Tree) 转载至:https://www.cnblogs.com/jielongAI/p/9565776.html 在学习算法的过程中,二叉平衡树是一定会碰到的,这篇博文尽可能简 ...

  5. 04-树5 Root of AVL Tree

    平衡二叉树 LL RR LR RL 注意画图理解法 An AVL tree is a self-balancing binary search tree. In an AVL tree, the he ...

  6. 数据结构树之AVL树(平衡二叉树)

    一 什么是AVL树(平衡二叉树): AVL树本质上是一颗二叉查找树,但是它又具有以下特点:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树.在AVL树中任何节 ...

  7. A1123. Is It a Complete AVL Tree

    An AVL tree is a self-balancing binary search tree. In an AVL tree, the heights of the two child sub ...

  8. 04-树5 Root of AVL Tree + AVL树操作集

    平衡二叉树-课程视频 An AVL tree is a self-balancing binary search tree. In an AVL tree, the heights of the tw ...

  9. PAT甲级1123. Is It a Complete AVL Tree

    PAT甲级1123. Is It a Complete AVL Tree 题意: 在AVL树中,任何节点的两个子树的高度最多有一个;如果在任何时候它们不同于一个,则重新平衡来恢复此属性.图1-4说明了 ...

  10. HDU 2193 AVL Tree

    AVL Tree An AVL tree is a kind of balanced binary search tree. Named after their inventors, Adelson- ...

随机推荐

  1. ehcache注解全面解析

    通过ehcache以编程方式使用缓存: 跟上面的方式相同,但是缓存通过ehcache去管理,当然比使用map有N多种好处,比如缓存太大了快达到上限之后,将哪一部分缓存清除出去.这种方式完全是通过代码的 ...

  2. C语言与汇编的嵌入式编程:统计字符串中各字符出现的次数

    原始C语言: #include<stdio.h> void main(){ ]; char pipei[] = "abcdefghijklmnopqrstuvwxyz" ...

  3. Laravel Vuejs 实战:开发知乎 (7)验证问题表单字段

    上一节代码中已经实现 下面代码中的validate内部配置就是: public function store(Request $request) { // $data = $request->v ...

  4. 分布式事务 --- BASE 理论

    部分图片总结出自参考资料 问题 : Base 理论为什么会被提出,动机是什么 Base 和 ACID 的区别与联系 概述 上一篇我们知道CAP 理论,也知道由于现实中网络等原因,分区容错性这一元素大多 ...

  5. LLC半桥谐振变换器调试记录

    1.判断二极管是否击穿 2.判断mos管是否烧坏 直接用声音档,发出响声说明击穿了 3.测试二极管的正负极方法 将万用表调到二极管档 1.信号发生芯片周围的电阻 2.反馈部分的电阻 3.实验准备部分: ...

  6. Linux : file命令

    file xxx file命令用来探测给定文件的类型.file命令对文件的检查分为文件系统.魔法幻数检查和语言检查3个过程 命令选项: -b:列出辨识结果时,不显示文件名称: -c:详细显示指令执行过 ...

  7. L3-023 计算图

    建立结构体保存每个结点的前驱,操作符,来回两遍拓扑排序~ #include<bits/stdc++.h> using namespace std; ; struct node { vect ...

  8. spring boot中配置文件中变量的引用

    配置文件中 变量的自身引用 ${名称} java文件中引用:非静态变量 之间在变量上面注释@Value("${名称}")  静态变量 在set方法上注释@Value("$ ...

  9. 实时监听 mysql 操作,Linux 版

    效果 场景:某数据库新增了某条记录,服务器可以监听到变化的数据与操作,如 增加一条记录: id = 1009,name=''test,number = 11 服务器监听结果: 实现过程 测试过程:数据 ...

  10. php类的魔术方法也就是带下划线的类方法介绍及应用

    001 PHP把所有以__(两个下划线)开头的类方法当成魔术方法,并且这些魔术方法的参数都不能通过引用传递.php的魔术方法有: 002  __construct(), __destruct(), _ ...