二叉排序树和AVL树
文章目录
引言:本文视频链接全部来自bilibili,因为是在bilibili大学上学qwq
一、二叉排序树
1. 理论定义
(1)、什么是二叉排序树
二叉排序树(Binary Sort Tree),又称二叉查找树(Binary Search Tree),亦称二叉搜索树。是数据结构中的一类。在一般情况下,查询效率比链表结构要高。 —— 百度百科
完整定义请看:=> 二叉排序树
(2)、简单介绍二叉排序树
安利bilibili机智牛牛小嗨嗨关于平衡二叉树
2. 模拟画图
如何在纸上画出二叉排序树?
建议食用bilibiliCUIT金牛老师二叉排序树qwq
3. 要点分析
掌握规则后,新来的元素向左或是向右理解了以后,还需要考虑二叉树的两种储存方式,一是数组模拟的顺序存储,二是链式存储;这两种方式截然不同,都需要掌握。本文着重介绍链式存储,顺带提一下顺序存储。
新元素在插入过程中,它的值需要不断地与当前走到的节点值相比较,如果新元素值更大,就走向当前节点的左儿子(或称左子树)上,反之,走到当前节点的右儿子(或称右子树)上。那么怎么"走"呢?
设顺序存储数组为tree[N]
-
二叉排序树顺序存储:
假设双亲结点下标为x,值记为p,
即 p = tree[x];那么它的左儿子下标记为lc,右儿子下标记为rc,
分两种情况
-
如果数组下标从0开始:那么有:
lc = 2 * x + 1、rc = 2 * x + 2
-
如果数组下标从1开始:那么有:
c = 2 * x、rc = 2 * x + 1
-
-
二叉排序树链式储存:
链式寻找左右儿子直接用指针即可
4. 代码实现
(1)、定义结构体:
typedef struct Node
{
int weight;
struct Node* lc, * rc;
}node, * tree;
(2)、插入新节点:
void Insert(tree &T, int w)
{
if (T == NULL) {
T = new node;
T->weight = w;
T->lc = T->rc = NULL;
} else {
if (T->weight < w) Insert(T->rc, w);
else Insert(T->lc, w);
}
}
(3)、层序遍历:
void TierTravel(tree &T)
{
queue <tree> q;
q.push(T);
while (!q.empty())
{
tree tmp = q.front(); q.pop();
cout << tmp->weight << '\n';
if (tmp->lc != NULL) q.push(tmp->lc);
if (tmp->rc != NULL) q.push(tmp->rc);
}
}
(4)、中序遍历:中序遍历二叉排序树可得到有序序列
void InOrderTravel(tree &T)
{
if (T)
{
InOrderTravel(T->lc);
cout << T->weight << '\n';
InOrderTravel(T->rc);
}
}
(5)、完整代码:
1、链式:
#include <iostream>
#include <cstdlib>
#include <queue>
using namespace std;
typedef struct Node
{
int weight;
struct Node* lc, * rc;
}node, * tree;
void Insert(tree &T, int w)
{
if (T == NULL)
{
T = new node;
T->weight = w;
T->lc = T->rc = NULL;
}
else
{
if (T->weight < w) Insert(T->rc, w);
else Insert(T->lc, w);
}
}
void InOrderTravel(tree &T)
{
if (T)
{
InOrderTravel(T->lc);
cout << T->weight << '\n';
InOrderTravel(T->rc);
}
}
int n, w;
int main()
{
tree T = NULL;
cin >> n;//共有n个数
srand((unsigned)time(NULL));
for (int i = 0; i < n; ++ i)
{
cin >> w;
Insert(T, w);
}
InOrderTravel(T);//测试,因为二叉排序树中序遍历可得到有序序列
system("pause");
return 0;
}
2、顺序:
#include <iostream>
using namespace std;
const int N = 100010;
int tree[2*N];
void Insert(int loc, int x)
{
if(!tree[loc]) tree[loc] = x;
else
{
if (tree[loc] >= x) Insert(loc * 2 + 1, x);
else Insert(loc * 2 + 2, x);
}
}
void Inorder(int loc)
{
if (!tree[loc]) return;
Inorder(loc * 2 + 1);
cout << tree[loc] << ' ';
Inorder(loc * 2 + 2);
}
int n, x;
int main()
{
cin >> n;
for (int i = 0; i < n; ++ i)
{
cin >> x;
Insert(0, x);
}
Inorder(0);
return 0;
}
二、AVL树
1. 理论定义
在计算机科学中,AVL树是最先发明的自平衡二叉查找树。在AVL树中任何节点的两个子树的高度最大差别为1,所以它也被称为高度平衡树。增加和删除可能需要通过一次或多次树旋转来重新平衡这个树。AVL树得名于它的发明者G. M. Adelson-Velsky和E. M. Landis,他们在1962年的论文《An algorithm for the organization of information》中发表了它。 ——百度百科
2. 模拟旋转
bilibili林语石AVL平衡调整
3. 代码实现
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
typedef struct Node
{
int weight, height;
struct Node* lc, * rc;
}Tnode, * tree;
int Getheight(tree &T)
{
if (!T) return 0;
return T->height;
}
Tnode* LLInsert(Tnode * A)
{
Tnode * B = A -> lc;
A -> lc = B -> rc;
B -> rc = A;
A ->height = max(Getheight(A->lc),Getheight(A->rc)) +1;
B ->height = max(Getheight(B->lc),A->height) +1;
return B ;
}
Tnode* RRInsert(Tnode *A)
{
Tnode *B = A -> rc;
A -> rc = B -> lc;
B -> lc = A ;
A ->height = max(Getheight(A->lc),Getheight(A->rc))+1;
B ->height = max(Getheight(B->lc),Getheight(B->rc))+1;
return B;
}
Tnode* LRInsert(Tnode *A)
{
A->lc = RRInsert(A->lc);
return LLInsert(A);
}
Tnode* RLInsert(Tnode *A)
{
A -> rc = LLInsert(A->rc);
return RRInsert(A);
}
Tnode * Insert(Tnode *T, int x)
{
if(!T)
{
T = new Tnode;
T -> weight = x;
T -> lc = T -> rc = NULL;
}
else if(x < T->weight)
{
T -> lc = Insert(T -> lc, x);
if(Getheight(T -> lc) - Getheight(T -> rc) == 2)
{
if(x < T -> lc ->weight) T = LLInsert(T);
else T = LRInsert(T);
}
}
else if(x > T->weight)
{
T -> rc = Insert(T -> rc, x);
if(Getheight(T -> lc) - Getheight(T -> rc) == -2)
if(x > T -> rc -> weight) T = RRInsert(T);
else T = RLInsert(T);
}
T -> height = max(Getheight(T -> lc),Getheight(T -> rc)) + 1;
return T;
}
void InOrderTravel(tree &T)
{
if (T)
{
InOrderTravel(T->lc);
cout << T->weight << '\n';
InOrderTravel(T->rc);
}
}
/*
void DFS(tree &T)
{
if (!T) return;
cout << T->weight << ' ';
DFS(T->lc);
DFS(T->rc);
}
*/
int n, w;
int main()
{
tree T = NULL;
cin >> n;
for (int i = 0; i < n; ++ i)
{
cin >>w;
T = Insert(T, w);
}
// DFS(T);
InOrderTravel(T);
system("pause");
return 0;
}
/*
2 7 4 5 8 6
*/
如果后面有时间,会更新AVL树的删除操作
TO BE CONTINUE…