這篇文章將為大家詳細講解有關AVL樹中如何插入,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。
AVL樹被稱為高度平衡的二叉搜索樹,盡量降低二叉樹的高度,來保持二叉樹的平衡,減少樹的平均搜索長度。
AVL樹的性質:1、左子樹和右子樹的高度之差(絕對值)不超過1
2、樹中的每棵子樹都是AVL樹,
3、每個節點都有一個平衡因子,取值為(-1,0,1),通過平衡因子來判斷樹的平衡。
AVL樹的插入需要考慮以下的幾種情況:(箭頭表示要插入的方向和節點)
第一種情況:插入的節點在20的右邊,但是這樣導致10的平衡因子大于1所以需要進行旋轉才能改變平衡因子

第二種情況:在左邊插入,導致平衡因子也不滿足條件,需要旋轉

第三種情況:插入的節點可能不構成單旋,所以需要雙旋來解決

第四種情況:與第三種情況相反的雙旋

如此通過旋轉就可以達到在插入的時候讓此二叉樹達到平衡。
實現代碼如下:
//main函數
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<assert.h>
using namespace std;
#include"AVLTree.h"
int main()
{
testAVLTree();
system("pause");
return 0;
}//AVLTree ----> 被稱為高度平衡的二叉搜索樹
//使用三叉鏈來實現此二叉平衡搜索樹
//性質:左右高度差不超過1 && 該樹的左右子樹都為二叉平衡樹
template<class K,class V>
struct AVLTreeNode
{
AVLTreeNode<K, V>* _left;
AVLTreeNode<K, V>* _right;
AVLTreeNode<K, V>* _parent;
K _key;
V _value;
int _bf; // 平衡因子
//構造函數
AVLTreeNode(const K& key,const V& value) :_left(NULL), _right(NULL), _parent(NULL)
, _key(key), _value(value), _bf(0)
{}
};
template<class K,class V>
class AVLTree
{
typedef AVLTreeNode<K,V> Node;
public:
AVLTree() :_root(NULL)
{}
//使用非遞歸的插入
bool Insert(const K& key, const V& value)
{
//如果根節點不存在說明插入的節點是第一個節點,直接new 一個即可
if (_root == NULL){
_root = new Node(key, value);
return true;
}
Node* cur = _root;
Node* parent = NULL;
while (cur)
{
if (cur->_key < key){
parent = cur;
cur = cur->_right;
}
else if (cur->_key>key){
parent = cur;
cur = cur->_left;
}
else{
return false;
}
}
//走到這里,說明這個節點不存在,先new
cur = new Node(key, value);
//比較插入節點的值與父節點的值,再考慮鏈上左還是右
if (parent->_key < key){
parent->_right = cur;
cur->_parent = parent;
}
else if (parent->_key>key){
parent->_left = cur;
cur->_parent = parent;
}
else{
while (parent)
{
//判斷cur是插在了parent的左邊還是右邊,再判斷平衡因子是++還是--
if (cur == parent->_left){
parent->_bf--;
}
else{
parent->_bf++;
}
//++或--之后,判斷平衡因子是否等于2或等于-2
if (parent->_bf == 0) //等于0說明沒有變,則跳出循環
{
break;
}
else if (parent->_bf == 1 || parent->_bf == -1)
{
cur = parent;
parent = cur->_parent;
}
else if (parent->_bf == 2 || parent->_bf == -2)//如果等于2或者等于-2則不再插入,先調節為二叉平衡樹再插入
{
//根據平衡因子來判斷需要調整的樹是哪種類型,再選擇單旋還是雙旋
//如果父節點的平衡因子等于2,說明右子樹比左子樹高,再判斷右子樹的子樹是在它的左邊還是右邊
if (parent->_bf == 2)
{
if (cur->_bf == 1){
RotateL(parent);
}
else{
RotateRL(parent);
}
}
else
{
if (cur->_bf == -1)
RotateR(parent);
else
RotateLR(parent);
}
}
}
}
return true;
}
//cur = parent;
//右單旋
void RotateR(Node* parent)
{
//需要記錄parent上面是否還有父親節點
Node* ppNode = parent->_parent;
Node* subL = parent->_left;
Node* subLR = subL->_right;
parent->_left = subLR;
//如果subLR存在 就將它的父親置為parent
if (subLR)
subLR->_parent = parent;
subL->_right = parent;
parent->_parent = subL;
//如果parent等于根節點,說明已經到第一個節點,不需要調整,直接將subL作為根即可
if (parent == _root)
{
_root = subL;
subL->_parent = NULL;
}
else //如果還沒有到根節點還需要判斷parent是左還是右
{
if (ppNode->_left == parent)
ppNode->_left = subL;
else{
ppNode->_right = subL;
}
subL->_parent = ppNode;
}
}
//左單旋
void RotateL(Node* parent)
{
Node* ppNode = parent->_parent;
Node* subR = parent->_right;
Node* subRL = subR->_left;
parent->_right = subRL;
//判斷subRL是否存在
if (subRL){
subRL->_parent = parent;
}
subR->_left = parent;
parent->_parent = subRL;
if (_root == parent)
{
_root = subR;
subR->_parent = NULL;
}
else
{
if (ppNode->_left == parent)
ppNode->_left = subR;
else
ppNode->_right = subR;
subR->_parent = ppNode;
}
}
//左右單旋
void RotateLR(Node* parent)
{
RotateL(parent->_right);
RotateR(parent);
}
//右左單旋
void RotateRL(Node* parent)
{
RotateR(parent->_left);
RotateL(parent);
}
void InOrder()
{
_InOrder(_root);
cout << endl;
}
void _InOrder(Node* root)
{
if (root == NULL)
return;
_InOrder(root->_left);
cout << root->_key << " ";
_InOrder(root->_right);
}
bool IsBalance()
{
return _IsBalance(_root);
}
bool _IsBalance(Node* root)
{
if (root == NULL)
return;
int leftheight = _Height(root->_left);
int rightheight = _Height(root->_right);
return abs(rightheight - leftheight) < 2 && _IsBalance(root->_left) && _IsBalance(root->_right);
}
size_t _Height(Node* root)
{
if (root == NULL)
return 0;
size_t left = _Height(root->_left);
size_t right = _Height(root->_right);
return left > right ? left + 1 : right + 1;
}
private:
Node* _root;
};
void testAVLTree()
{
AVLTree<int, int> t;
int a[] = { 16,3,7,11,9,26,18,14,15};
for (int i = 0; i < (sizeof(a) / sizeof(a[0])); i++)
{
cout<<t.Insert(a[i], 0)<<endl;
}
t.InOrder();
}關于“AVL樹中如何插入”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。