此文转载:

http://www.cnblogs.com/skywang12345/p/3577360.html

AVL树是一棵特殊的高度平衡的二叉树,每个节点的两棵子树高度最大差为1。所以在每次的删除或者是插入的过程之后都要判断此时是否是一颗AVL树,AVL树不平衡的调整最关键,大概分为四种不同的不平衡的状态。处理四种不平衡状态四个调整函数(LL,RR,LR,Rl)即可;

(1) LL:LeftLeft,也称为"左左"。插入或删除一个节点后,根节点的左子树的左子树还有非空子节点,导致"根的左子树的高度"比"根的右子树的高度"大2,导致AVL树失去了平衡。

例如,在上面LL情况中,由于"根节点(8)的左子树(4)的左子树(2)还有非空子节点",而"根节点(8)的右子树(12)没有子节点";导致"根节点(8)的左子树(4)高度"比"根节点(8)的右子树(12)"高2。

(2) LR:LeftRight,也称为"左右"。插入或删除一个节点后,根节点的左子树的右子树还有非空子节点,导致"根的左子树的高度"比"根的右子树的高度"大2,导致AVL树失去了平衡。

例如,在上面LR情况中,由于"根节点(8)的左子树(4)的左子树(6)还有非空子节点",而"根节点(8)的右子树(12)没有子节点";导致"根节点(8)的左子树(4)高度"比"根节点(8)的右子树(12)"高2。

(3) RL:RightLeft,称为"右左"。插入或删除一个节点后,根节点的右子树的左子树还有非空子节点,导致"根的右子树的高度"比"根的左子树的高度"大2,导致AVL树失去了平衡。

例如,在上面RL情况中,由于"根节点(8)的右子树(12)的左子树(10)还有非空子节点",而"根节点(8)的左子树(4)没有子节点";导致"根节点(8)的右子树(12)高度"比"根节点(8)的左子树(4)"高2。

(4) RR:RightRight,称为"右右"。插入或删除一个节点后,根节点的右子树的右子树还有非空子节点,导致"根的右子树的高度"比"根的左子树的高度"大2,导致AVL树失去了平衡。

例如,在上面RR情况中,由于"根节点(8)的右子树(12)的右子树(14)还有非空子节点",而"根节点(8)的左子树(4)没有子节点";导致"根节点(8)的右子树(12)高度"比"根节点(8)的左子树(4)"高2。

LL旋转:

RR旋转:

LR旋转:

RL旋转:

因为博客园中我还不知道如何转载原文,所以只能以这种方式;

第八次作业:

下面是我自己根据原文代码做题写的C语言的代码(没有全A,不知为何)

2、题目链接(多次删除操作多次寻找树中的最大最小值):

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<malloc.h>
using namespace std;
int n;
int nodes[100005];
int dep[100005];
int depth = 0;
typedef struct AVL_Node
{
int data;
int height;
AVL_Node* left;
AVL_Node* right;
}Node, *AVLTree; int MAX(int a, int b)
{
return a < b ? b : a;
} int Height(AVLTree tree) //返回该节点树的高度;
{
return tree == NULL ? 0 : tree->height;
} Node* create_node(int data, Node* left, Node* right)
{
Node* p;
if ((p = (Node*)malloc(sizeof(Node))) == NULL)
return NULL;
p->data = data;
p->height = 0;
p->left = left;
p->right = right;
return p;
} Node* L_L(AVLTree tree)
{
AVLTree tmp;
tmp = tree->left;
tree->left = tmp->right;
tmp->right = tree;
tree->height = MAX(Height(tree->left), Height(tree->right)) + 1;
tmp->height = MAX(Height(tmp->left), tree->height) + 1;
return tmp;
} Node* R_R(AVLTree tree)
{
AVLTree tmp;
tmp = tree->right;
tree->right = tmp->left;
tmp->left = tree;
tree->height = MAX(Height(tree->left), Height(tree->right)) + 1;
tmp->height = MAX(Height(tmp->right), tree->height) + 1;
return tmp;
} Node* L_R(AVLTree tree)
{
tree->left = R_R(tree->left);
return L_L(tree);
} Node* R_L(AVLTree tree)
{
tree->right = L_L(tree->right);
return R_R(tree);
}
Node* maximum(Node* tree)
{
if (tree == NULL)return NULL;
while(tree->right!=NULL)
{
tree = tree->right;
}
return tree;
}
Node* minimun(Node* tree)
{
if (tree == NULL)return NULL;
while(tree->left!=NULL)
{
tree = tree->left;
}
return tree;
} Node* insert(AVLTree tree, int data)
{
if (tree == NULL)
{
tree = create_node(data, NULL, NULL);
if (tree == NULL)
return NULL;
}
else if (data < tree->data) //根据AVL树的性质应该插入到左子树中
{
tree->left = insert(tree->left, data);
if (Height(tree->left) - Height(tree->right) == 2) //插入后树如果不平衡,则应进行调节;
{
if (data < tree->left->data)
tree = L_L(tree);
else
tree = L_R(tree);
}
}
else if (data > tree->data)
{
tree->right = insert(tree->right, data);
if (Height(tree->right) - Height(tree->left) == 2)
{
if (data < tree->right->data)
tree = R_L(tree);
else
tree = R_R(tree);
}
}
tree->height = MAX(Height(tree->left), Height(tree->right)) + 1;
return tree;
} Node* Delete(AVLTree tree,Node* dele)
{
if (tree == NULL || dele == NULL)return NULL; //根为空或者没有要删除的节点,直接返回NULL;
if (dele->data < tree->data) //删除节点在左子树中;
{
tree->left = Delete(tree->left, dele);
if (Height(tree->right) - Height(tree->left) == 2)//失去平衡之后要重新调整;
{
Node* tmp = tree->right;
if (Height(tmp->left) > Height(tmp->right))
tree = R_L(tree);
else
tree = R_R(tree);
}
}
else if (dele->data > tree->data) //删除节点在右子树中;
{
tree->right = Delete(tree->right, dele);
if (Height(tree->left) - Height(tree->right) == 2)//失去平衡之后要重新调整;
{
Node* tmp = tree->left;
if (Height(tmp->right) > Height(tmp->left))
tree = L_R(tree);
else
tree = L_L(tree);
}
}
else
{
if ((tree->left != NULL) && (tree->right != NULL))
{
if (Height(tree->left) > Height(tree->right))
{
// 如果tree的左子树比右子树高;
// 则(01)找出tree的左子树中的最大节点
// (02)将该最大节点的值赋值给tree。
// (03)删除该最大节点。
// 这类似于用"tree的左子树中最大节点"做"tree"的替身;
// 采用这种方式的好处是:删除"tree的左子树中最大节点"之后,AVL树仍然是平衡的。
Node* max = maximum(tree->left);
tree->data = max->data;
tree->left = Delete(tree->left, max);
}
else
{
// 如果tree的左子树不比右子树高(即它们相等,或右子树比左子树高1)
// 则(01)找出tree的右子树中的最小节点
// (02)将该最小节点的值赋值给tree。
// (03)删除该最小节点。
// 这类似于用"tree的右子树中最小节点"做"tree"的替身;
// 采用这种方式的好处是:删除"tree的右子树中最小节点"之后,AVL树仍然是平衡的。
Node* min = minimun(tree->right);
tree->data = min->data;
tree->right = Delete(tree->right, min);
}
}
else
{
Node* tmp = tree;
tree = (tree->left != NULL) ? tree->left : tree->right;
free(tmp);
}
}
return tree;
} Node* mininode(AVLTree tree,AVLTree tmproot) //寻找最小键值的节点;
{
int depth = 1;
if (tree == NULL)return NULL;
while (tree->left != NULL)
{
tree = tree->left; depth++;
}
cout << tree->data << " " << depth << endl;
return Delete(tmproot, tree);
} Node* maxnode(AVLTree tree,AVLTree tmproot) //寻找最大键值的节点;
{
int depth = 1;
if (tree == NULL)return NULL;
while (tree->right != NULL)
{
tree = tree->right; depth++;
}
cout << tree->data << " " << depth << endl;
return Delete(tmproot, tree);
} int main()
{
int i, tmp1, tmp2;
AVLTree root = NULL;
cin >> n;
for (i = 1; i <= n; i++)
{
cin >> nodes[i];
root = insert(root, nodes[i]);
}
int m, j = 0;
cin >> m;
for (i = 1; i <= m; i++)
{
cin >> tmp1;
if (tmp1 == 1)
{
if (j >= n) { cout << "-1\n"; continue; }
root = maxnode(root, root); j++;
}
else if (tmp1 == 2)
{
if (j >= n) { cout << "-1\n"; continue; }
root = mininode(root, root); j++;
}
else if (tmp1 == 3)
{
cin >> tmp2;
insert(root, tmp2);
j--;
}
}
return 0;
}

1、题目链接(找出每个节点的深度即层次)

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<malloc.h>
using namespace std;
int n;
int nodes[100005];
int dep[100005];
int depth = 0;
typedef struct AVL_Node
{
int data;
int height;
AVL_Node* left;
AVL_Node* right;
}Node, *AVLTree; int MAX(int a, int b)
{
return a < b ? b : a;
} int Height(AVLTree tree)
{
return tree == NULL ? 0 : tree->height;
} Node* create_node(int data, Node* left, Node* right)
{
Node* p;
if ((p = (Node*)malloc(sizeof(Node))) == NULL)
return NULL;
p->data = data;
p->height = 0;
p->left = left;
p->right = right;
return p;
} Node* L_L(AVLTree tree)
{
AVLTree tmp;
tmp = tree->left;
tree->left = tmp->right;
tmp->right = tree;
tree->height = MAX(Height(tree->left), Height(tree->right)) + 1;
tmp->height = MAX(Height(tmp->left), tree->height) + 1;
return tmp;
} Node* R_R(AVLTree tree)
{
AVLTree tmp;
tmp = tree->right;
tree->right = tmp->left;
tmp->left = tree;
tree->height = MAX(Height(tree->left), Height(tree->right)) + 1;
tmp->height = MAX(Height(tmp->right), tree->height) + 1;
return tmp;
} Node* L_R(AVLTree tree)
{
/*AVLTree tmp1, tmp2;
tmp2 = tree->left;
tmp1 = tmp2->right;
tmp2->right = tmp1->left;
tmp1->left = tmp2;
tree->left = tmp1;*/
tree->left = R_R(tree->left);
return L_L(tree);
} Node* R_L(AVLTree tree)
{
tree->right = L_L(tree->right);
return R_R(tree);
} Node* insert(AVLTree tree, int data)
{
if (tree == NULL)
{
tree = create_node(data, NULL, NULL);
if (tree == NULL)
return NULL;
}
else if (data < tree->data) //根据AVL树的性质应该插入到左子树中
{
tree->left = insert(tree->left, data);
if (Height(tree->left) - Height(tree->right) == 2)
{
if (data < tree->left->data)
tree = L_L(tree);
else
tree = L_R(tree);
}
}
else if (data > tree->data)
{
tree->right = insert(tree->right, data);
if (Height(tree->right) - Height(tree->left) == 2)
{
if (data < tree->right->data)
tree = R_L(tree);
else
tree = R_R(tree);
}
}
tree->height = MAX(Height(tree->left), Height(tree->right)) + 1;
return tree;
} void mid_Tree(AVLTree tree) //中序遍历树,即从小到大遍历
{
if (tree != NULL)
{
depth++; //每向下走一步就加一
mid_Tree(tree->left);
dep[tree->data] = depth;
mid_Tree(tree->right);
depth--; //往上回走一步减一(回溯过程)
}
}
int main()
{
int i, tmp;
AVLTree root = NULL;
cin >> n;
for (i = 1; i <= n; i++)
{
cin >> nodes[i];
root = insert(root, nodes[i]);
}
mid_Tree(root);
for (i = 1; i <= n; i++)
printf("%d%c", dep[nodes[i]], i != n ? ' ' : '\n');
return 0;
}

其次我认为最主要是给定一个数列之后,会将其AVL树画出来;

具体可以参见博客:http://www.cnblogs.com/skywang12345/p/3577360.html

AVL树/线索二叉树的更多相关文章

  1. PAT甲级题解-1123. Is It a Complete AVL Tree (30)-AVL树+满二叉树

    博主欢迎转载,但请给出本文链接,我尊重你,你尊重我,谢谢~http://www.cnblogs.com/chenxiwenruo/p/6806292.html特别不喜欢那些随便转载别人的原创文章又不给 ...

  2. 二叉树与AVL树

    二叉树 什么是二叉树? 父节点至多只有两个子树的树形结构成为二叉树.如下图所示,图1不是二叉树,图2是一棵二叉树. 图1 普通的树                                    ...

  3. 【Java】 大话数据结构(9) 树(二叉树、线索二叉树)

    本文根据<大话数据结构>一书,对Java版的二叉树.线索二叉树进行了一定程度的实现. 另: 二叉排序树(二叉搜索树) 平衡二叉树(AVL树) 二叉树的性质 性质1:二叉树第i层上的结点数目 ...

  4. PAT树_层序遍历叶节点、中序建树后序输出、AVL树的根、二叉树路径存在性判定、奇妙的完全二叉搜索树、最小堆路径、文件路由

    03-树1. List Leaves (25) Given a tree, you are supposed to list all the leaves in the order of top do ...

  5. 二叉树学习笔记之经典平衡二叉树(AVL树)

    二叉查找树(BSTree)中进行查找.插入和删除操作的时间复杂度都是O(h),其中h为树的高度.BST的高度直接影响到操作实现的性能,最坏情况下,二叉查找树会退化成一个单链表,比如插入的节点序列本身就 ...

  6. 二叉树-二叉查找树-AVL树-遍历

    一.二叉树 定义:每个节点都不能有多于两个的儿子的树. 二叉树节点声明: struct treeNode { elementType element; treeNode * left; treeNod ...

  7. 数据结构与算法系列研究五——树、二叉树、三叉树、平衡排序二叉树AVL

    树.二叉树.三叉树.平衡排序二叉树AVL 一.树的定义 树是计算机算法最重要的非线性结构.树中每个数据元素至多有一个直接前驱,但可以有多个直接后继.树是一种以分支关系定义的层次结构.    a.树是n ...

  8. 二叉树,AVL树和红黑树

    为了接下来能更好的学习TreeMap和TreeSet,讲解一下二叉树,AVL树和红黑树. 1. 二叉查找树 2. AVL树 2.1. 树旋转 2.1.1. 左旋和右旋 2.1.2. 左左,右右,左右, ...

  9. 树和二叉树->线索二叉树

    文字描述 从二叉树的遍历可知,遍历二叉树的输出结果可看成一个线性队列,使得每个结点(除第一个和最后一个外)在这个线形队列中有且仅有一个前驱和一个后继.但是当采用二叉链表作为二叉树的存储结构时,只能得到 ...

随机推荐

  1. 泰坦尼克(Titanic)生存因素可视化

    数据来源: kaggle 分析工具:Python 3.6 & jupyter notebook 附上数据:链接: https://pan.baidu.com/s/1D7JNvHmqTIw0Oo ...

  2. c#操作注册表的意外

    因为要在C/S程序中使用WebBrowser控件,因为默认的IE版本很低,无法使用Html5功能,故需通过把程序名写入注册表的方法指定IE版本. 但操作的过程中出现一个问题: 1.使用代码找到相关项, ...

  3. 2017-2018-1 20155214 《信息安全系统设计基础》 第9周课下测试-mypwd

    2017-2018-1 20155214 <信息安全系统设计基础> 第9周课下测试-mypwd(深入版) 题目要求: 1 学习pwd命令 2 研究pwd实现需要的系统调用(man -k; ...

  4. 20155231 邵煜楠《网络对抗技术》实验一 PC平台逆向破解

    20155231 邵煜楠<网络对抗技术>实验一 PC平台逆向破解 实验内容 直接修改程序机器指令,改变程序执行流程: 通过构造输入参数,造成BOF攻击,改变程序执行流: 注入Shellco ...

  5. Caffe on Windows (Visual Studio 2015+CUDA8.0+cuDNNv5)

    Title : Caffe (Visual Studio15+CUDA8+cuDNN5+python3.5) Author : SURFZJY Logo : True [TITLE] Requirem ...

  6. 【转载】C++创建对象的两种方法

    原文:http://blog.sina.com.cn/s/blog_586b6c050100dhjg.html 在C++里,有两种方法创建对象: 方法一: ClassName object(param ...

  7. JavaScript验证时间格式

    1. 短时间,形如 (13:04:06) function isTime(str) { var a = str.match(/^(\d{1,2})(:)?(\d{1,2})\2(\d{1,2})$/) ...

  8. axios的简单使用

    axios是一个通用的ajax请求库,vue 2.0以后,推荐使用axios Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中. 使用: 1.下载安装 n ...

  9. spring cloud网关通过Zuul RateLimit 限流配置

    目录 引入依赖 配置信息 RateLimit源码简单分析 RateLimit详细的配置信息解读 在平常项目中为了防止一些没有token访问的API被大量无限的调用,需要对一些服务进行API限流.就好比 ...

  10. 随机游走模型(RandomWalk Mobility)

    随机游走模型由首先由爱因斯坦在1926年以数学方式描述.由于自然界中的许多实体会以不可预知的方式移动,因此随机游走模型用来描述这种不稳定的移动.在这种移动模型中,移动节点随机选择一个方向和速度来从当前 ...