大師兄的數(shù)據(jù)結(jié)構(gòu)學(xué)習(xí)筆記(五):二叉樹(shù)
大師兄的數(shù)據(jù)結(jié)構(gòu)學(xué)習(xí)筆記(七):堆
一、二叉搜索樹(shù)(Binary Search Tree)
1. 什么是二叉搜索樹(shù)
- 一棵二叉樹(shù),可以為空。
- 如果不為空,滿(mǎn)足以下性質(zhì):
1) 非空左子樹(shù)的所有鍵值小于其根結(jié)點(diǎn)的鍵值。
2) 非空右子樹(shù)的所有鍵值大于其根結(jié)點(diǎn)的鍵值。
3) 左、右子樹(shù)都是二叉搜索樹(shù)。
2. 特殊函數(shù):
| 函數(shù) | 描述 |
|---|---|
| BSDNode Find(ElementType X,BSTree BST) | 從二叉搜索樹(shù)BST中查找元素X,返回器所在結(jié)點(diǎn)的地址。 |
| BSDNode FindMin(BSTree BST) | 從二叉搜索樹(shù)BST中查找并返回最小元素所在結(jié)點(diǎn)的地址。 |
| BSDNode FindMax(BSTree BST) | 從二叉搜索樹(shù)BST中查找并返回最大元素所在結(jié)點(diǎn)的地址。 |
| BSTree Insert(ElementType X,BSTree BST) | 插入結(jié)點(diǎn) |
| BSTree Delete(ElementType X,BSTree BST) | 刪除結(jié)點(diǎn) |
3. 實(shí)現(xiàn)二叉搜索樹(shù)
#ifndef BINARYSEARCHTREE
#define BINARYSEARCHTREE
using namespace std;
template<typename T>
class BSTNode
{
////結(jié)點(diǎn)結(jié)構(gòu)
public:
T _key; //key
BSTNode* _lchild; //leftchild
BSTNode* _rchild; //rightchild
BSTNode* _parent; //parent
//構(gòu)造函數(shù)
BSTNode(
T key,
BSTNode* lchild,
BSTNode* rchild,
BSTNode* parent
) :
_key(key),
_lchild(lchild),
_rchild(rchild),
_parent(parent){};
};
template<typename T>
class BSTree
{
public:
BSTree() :_Root(NULL) {}; //構(gòu)造函數(shù)
~BSTree() {}; //析構(gòu)函數(shù)
BSTNode<T> Find(BSTNode<T>* &tree,T key) const; //查找結(jié)點(diǎn)
BSTNode<T> FindMin(BSTNode<T>* &tree); //查找最小結(jié)點(diǎn)
BSTNode<T> FindMax(BSTNode<T>* &tree); //查找最大結(jié)點(diǎn)
void Insert(BSTNode<T>* &tree, BSTNode<T>* z); //插入結(jié)點(diǎn)
BSTNode<T> Delete(BSTNode<T>* &tree, T key); //刪除結(jié)點(diǎn)
private:
BSTNode<T>* _Root; //根節(jié)點(diǎn)
};
#endif
#include "BinarySearchTree.h"
using namespace std;
template<typename T>
// 查找結(jié)點(diǎn)
BSTNode<T> BSTree<T>::Find(BSTNode<T>* &tree, T key) const
{
BSTNode<T>* temp = tree;
while (temp != nullptr)
{
if (temp->_key == key)
return temp;
else if (temp->_key > key)
temp = temp->_lchild;
else
temp = temp->_rchild;
}
}
template<typename T>
// 查找最小結(jié)點(diǎn)
BSTNode<T> BSTree<T>::FindMin(BSTNode<T>* &tree)
{
BSTNode<T>* temp = tree;
while (temp->_lchild)
{
temp = temp->_lchild;
}
return temp;
}
template<typename T>
// 查找最大結(jié)點(diǎn)
BSTNode<T> BSTree<T>::FindMax(BSTNode<T>* &tree)
{
BSTNode<T>* temp = tree;
while (temp->_rchild)
{
temp = temp->_rchild;
}
return temp;
}
template<typename T>
// 插入結(jié)點(diǎn)
void BSTree<T>::Insert(BSTNode<T>* &tree, BSTNode<T>* z)
{
BSTNode<T>* parent = nullptr;
BSTNode<T>* temp = tree;
// 尋找插入點(diǎn)
while (temp != nullptr)
{
parent = temp;
if (z->_key > temp->_key)
temp = temp->_rchild;
else
temp = temp->_left;
}
z->_parent = parent;
}
template<typename T>
//刪除結(jié)點(diǎn)
BSTNode<T> BSTree<T>::Delete(BSTNode<T>* &tree, T key)
{
BSTNode<T> temp = nullptr;
if (!tree)
printf("未找到要?jiǎng)h除的元素");
else if (key < tree->_key)
tree->_lchild = Delete(tree->_lchild,key); // 左子樹(shù)遞歸刪除
else if (key > tree->_key)
tree->_rchild = Delete(tree->_rchild,key); // 右子樹(shù)遞歸刪除
else // 如果找到了元素
if (tree->_lchild && tree->_rchild) // 包含左右兩個(gè)結(jié)點(diǎn)
{
temp = FindMin(tree->_rchild); // 找到右子樹(shù)中最小的元素用來(lái)填充結(jié)點(diǎn)
tree->_key = temp->_key;
tree->_rchild = Delete(tree->_rchild, tree->_key);
}
else // 只有一個(gè)結(jié)點(diǎn)或無(wú)子節(jié)點(diǎn)
{
temp = tree;
if (!tree->_lchild)
tree = tree->_rchild;
else if (!tree->_rchild)
tree = tree->_lchild;
}
return tree;
}
二、平衡二叉樹(shù) AVL樹(shù)(Balance Binary Tree)
- 由于二叉查找樹(shù)的查找效率取決于二叉排序樹(shù)的形態(tài),而構(gòu)造一棵形態(tài)均勻的二叉查找樹(shù)與節(jié)點(diǎn)插入的次序有關(guān),而插入的順序往往是不可預(yù)測(cè)的。
- 二叉查找樹(shù)形態(tài)越均勻,查找效率越高,介于
。
- 所以需要找到一種動(dòng)態(tài)平衡的方法,對(duì)于任意的插入序列都能構(gòu)造一棵形態(tài)均勻、平衡的二叉查找樹(shù),即平衡二叉樹(shù)。
1. 關(guān)于平衡二叉樹(shù)
- 任一結(jié)點(diǎn)左右子樹(shù)高度差的絕對(duì)值不超過(guò)1
。
-
根節(jié)點(diǎn)的左子樹(shù)和右子樹(shù)都是一顆平衡二叉樹(shù)。
2. 關(guān)于平衡因子
- 每個(gè)結(jié)點(diǎn)的平衡因子是該結(jié)點(diǎn)的左子樹(shù)與右子樹(shù)的深度之差。
3. 平衡二叉樹(shù)的調(diào)整
- 在向平衡二叉樹(shù)插入結(jié)點(diǎn)時(shí),需要檢查插入后是否破壞了樹(shù)的平衡性,如破壞則需要對(duì)樹(shù)進(jìn)行調(diào)整,主要有以下四種調(diào)整方式:
1) RR型
- 新插入的結(jié)點(diǎn)是插在結(jié)點(diǎn)A的右子樹(shù)的右子樹(shù)上,需要RR旋轉(zhuǎn)(右單旋)。
2) LL型
- 新插入的結(jié)點(diǎn)是插在結(jié)點(diǎn)A的左子樹(shù)的左子樹(shù)上,需要LL旋轉(zhuǎn)(左單旋)。
3) LR型
- 新插入的結(jié)點(diǎn)是插在結(jié)點(diǎn)A的左子樹(shù)的右子樹(shù)上,需要LR旋轉(zhuǎn)(先向左,再向右)。
4) RL型
- 新插入的結(jié)點(diǎn)是插在結(jié)點(diǎn)A的右子樹(shù)的左子樹(shù)上,需要RL旋轉(zhuǎn)(先向右,再向左)。
4. 實(shí)現(xiàn)平衡二叉樹(shù)
#ifndef AVLTREE
#define AVLTREE
using namespace std;
template<class DataType>
//結(jié)點(diǎn)結(jié)構(gòu)
struct Node
{
DataType data;
struct Node* lChild;
struct Node* rChild;
int balanceFactor; //平衡因子
};
template<class DataType>
class AVLTree
{
public:
AVLTree(Node<DataType>*& T); //構(gòu)造函數(shù)
~AVLTree() { destroy(root); }; //析構(gòu)函數(shù)
void insert(Node < DataType>*& T, Node < DataType>* S); // 插入結(jié)點(diǎn)
void createBalanceBiTreeFromArray(Node<DataType>*& T, DataType A[], int n); //創(chuàng)建AVL
void destroy(Node < DataType>*& T); // 銷(xiāo)毀二叉樹(shù)
void deleteNode(Node < DataType>*& T, DataType x); // 刪除結(jié)點(diǎn)
void LLAdjust(Node < DataType>*& T, Node < DataType>*& p, Node < DataType>*& f); //LL調(diào)整
void RRAdjust(Node < DataType>*& T, Node < DataType>*& p, Node < DataType>*& f); //RR調(diào)整
void LRAdjust(Node < DataType>*& T, Node < DataType>*& p, Node < DataType>*& f); //LR調(diào)整
void RLAdjust(Node < DataType>*& T, Node < DataType>*& p, Node < DataType>*& f); //RL調(diào)整
void AllAdjust(Node<DataType>*& T); // 調(diào)整AVL
void nodeFactorIsTwoFather(Node<DataType>*& T, Node<DataType>*& f); //獲得平衡因子為2或-2的節(jié)點(diǎn)的父節(jié)點(diǎn)
void nodeFactorIsTwo(Node<DataType>*& T, Node<DataType>*& p); //獲得平衡因子為2或-2的節(jié)點(diǎn)
int getNodeFactor(Node < DataType>* T); //求結(jié)點(diǎn)的平衡因子
void factorForTree(Node<DataType>*& T); //求樹(shù)的平衡因子
int BiTreeDepth(Node < DataType>* T); //求樹(shù)的高度
Node<DataType>* getElementFatherPointer(Node <DataType>*& T, Node <DataType>*& f, DataType x); //獲取父指針
void preOrderTraverse(Node<DataType>* T, int level); //先序遍歷輸出
void search(Node<DataType>*& T, Node<DataType>*& p, DataType x); // 查找元素
private:
Node<DataType>* root; //根結(jié)點(diǎn)
};
#endif
#include <iostream>
#include "AVLTree.h"
using namespace std;
template< class DataType>
AVLTree<DataType>::AVLTree(Node<DataType>*& T)
{
T = NULL;
}
template<class DataType>
//插入結(jié)點(diǎn)
void AVLTree<DataType>::insert(Node < DataType>*& T, Node < DataType>* S)
{
if (T == nullptr)
{
T = S;
}
else if (S->data < T->data)
{
insert(T->lChild, S);
}
else
{
insert(T->rChild, S);
}
}
template<class DataType>
//創(chuàng)建AVL
void AVLTree<DataType>::createBalanceBiTreeFromArray(Node<DataType>*& T, DataType A[], int n)
{
Node<DataType>* S, * p;
int i = 1;
T = new Node<DataType>;
T->balanceFactor = 0;
T->lChild = nullptr;
T->rChild = nullptr;
p = T;
T->data = A[0];
n = n - 1;
while (n)
{
S = new Node<DataType>;
S->data = A[i];
S->balanceFactor = 0;
S->lChild = nullptr;
S->rChild = nullptr;
insert(p, S);
AllAdjust(T);
p = T;
i++;
n--;
}
}
template<class DataType>
//銷(xiāo)毀AVLTree
void AVLTree<DataType>::destroy(Node < DataType>*& T)
{
if (T)
{
destroy(T->lChild);
destroy(T->rChild);
delete T;
}
}
template<class DataType>
// 刪除結(jié)點(diǎn)
void AVLTree<DataType>::deleteNode(Node < DataType>*& T, DataType x)
{
Node <DataType>* f, * p = nullptr;
search(T, p, x); // 查找結(jié)點(diǎn)
getElementFatherPointer(T, f, x);
if (p == nullptr)
{
// 如果沒(méi)找到結(jié)點(diǎn)
cout << "未找到結(jié)點(diǎn)." << endl;
return;
}
if (p->lChild == nullptr && p->rChild == nullptr)
{
//如果為葉節(jié)點(diǎn)
if (T == p)
{
// 如果根節(jié)點(diǎn)
delete p;
T = nullptr;
}
else
{
// 如果是非根節(jié)點(diǎn)
if (f->lChild == p)
{
delete p;
f->lChild = nullptr;
}
else {
delete p;
f->rChild = nullptr;
}
}
}
else if ((p->lChild == nullptr && p->rChild != nullptr) || (p->lChild != nullptr && p->rChild == nullptr))
{
// 如果有一邊為空
if (T == p)
{
if (T->lChild == nullptr&&T->rChild!=nullptr)
{
T = p->rChild;
delete p;
}
if (T->rChild == nullptr && T->lChild != nullptr)
{
T = p->lChild;
delete p;
}
}
else
{
if (p->lChild != nullptr)
{
if (f->lChild == p)
{
f->lChild = p->lChild;
}
else
{
f->rChild = p->lChild;
}
}
if (p->rChild != nullptr)
{
if (f->lChild == p)
{
f->lChild = p->rChild;
}
else
{
f->rChild = p->rChild;
}
}
}
}
else {
// 如果有兩個(gè)子樹(shù)
Node <DataType>* f, * next, * prior;
if (p ->balanceFactor==1)
{
//平衡因子為1
prior = getElementPriorPointer(p->lChild);
if (prior->lChild != nullptr && prior->rChild == nullptr)
{
p->data = prior->data;
prior->data = prior->lChild->data;
delete prior->lChild;
prior->lChild = nullptr;
}
if (prior->lChild == nullptr && prior->rChild == nullptr)
{
getElementFatherPointer(T, f, prior->data);
p->data = prior->data;
delete prior;
f->rChild = nullptr;
}
}
else if (p->balanceFactor == -1)
{
//平衡因子為-1
next = getElementNextPointer(p->rChild);
cout << next->data;
int level = 1;
if (next->rChild != nullptr && next->lChild == nullptr)
{
p->data = next->data;
next->data = next->rChild->data;
delete next->rChild;
next->rChild = nullptr;
}
else if (next->rChild == nullptr && next->lChild == nullptr)
{
getElementFatherPointer(T, f, next->data);
p->data = next->data;
delete next;
f->lChild = nullptr;
}
}
else if (p->balanceFactor == 0)
{
//平衡因子為0
prior = getElementPriorPointer(p->lChild);
if (prior->lChild != nullptr && prior->rChild == nullptr)
{
p->data = prior->data;
prior->data = prior->lChild->data;
delete prior->lChild;
prior->lChild = nullptr;
}
if (prior->lChild == nullptr && prior->rChild == nullptr)
{
getElementFatherPointer(T, f, prior->data);
p->data = prior->data;
delete prior;
if (p == f)
f->lChild = nullptr;
else
f->rChild = nullptr;
}
}
}
if (T != nullptr)
{
// 調(diào)整AVL
AllAdjust(T);
}
}
template<class DataType>
//LL調(diào)整
void AVLTree<DataType>::LLAdjust(Node < DataType>*& T, Node < DataType>*& p, Node < DataType>*& f)
{
Node<DataType>* r;
cout << "LL adjust" << endl;
if (T == p)
{
T = p->lChild; //將P的左孩子提升為新的根節(jié)點(diǎn)
r = T->rChild;
T->rChild = p;
p->lChild = r;
}
else
{
if (f->lChild == p) //f的左子樹(shù)是p
{
f->lChild = p->lChild;
r = f->lChild->rChild;
f->lChild->rChild = p;
p->lChild = r;
}
if (f->rChild == p) //f的右子樹(shù)是p
{
f->rChild = p->lChild;
r = f->rChild->rChild;
f->rChild->rChild = p;
p->rChild = r;
}
}
}
template<class DataType>
//RR調(diào)整
void AVLTree<DataType>::RRAdjust(Node < DataType>*& T, Node < DataType>*& p, Node < DataType>*& f)
{
Node<DataType>* l;
cout << "RR adjust" << endl;
if (T == p)
{
T = p->rChild;
l = T->lChild;
T->lChild = p;
p->rChild = l;
}
else
{
if (f->rChild == p)
{
f->rChild = p->rChild;
l = f->rChild->lChild;
f->rChild->lChild = p;
p->rChild = l;
}
if (f->lChild == p)
{
f->lChild = p->rChild;
l = f->lChild->lChild;
f->lChild->lChild = p;
p->rChild = l;
}
}
}
template<class DataType>
//LR調(diào)整
void AVLTree<DataType>::LRAdjust(Node < DataType>*& T, Node < DataType>*& p, Node < DataType>*& f)
{
Node<DataType>* l, * r;
cout << "LR adjust" << endl;
if (T == p)
{
T = p->lChild->rChild;
r = T->rChild;
l = T->rChild;
T->rChild = p;
T->lChild = p->lChild;
T->lChild->rChild = l;
T->rChild->lChild = r;
}
else
{
if (f->lChild == p)
{
f->lChild = p->lChild->rChild;
l = f->lChild->lChild;
r = f->lChild->rChild;
f->lChild->lChild = p->lChild;
f->rChild->rChild = p;
f->lChild->lChild->rChild = l;
p->lChild->rChild->lChild = r;
}
if (f->rChild == p)
{
f->rChild = p->lChild->rChild;
l = f->rChild->lChild;
r = f->rChild->rChild;
f->rChild->rChild = p;
f->rChild->lChild = p->lChild;
f->rChild->lChild->rChild = l;
f->rChild->rChild->lChild = r;
}
}
}
template<class DataType>
//RL調(diào)整
void AVLTree<DataType>::RLAdjust(Node < DataType>*& T, Node < DataType>*& p, Node < DataType>*& f)
{
Node<DataType>* l, * r;
cout << "RL adjust" << endl;
if (T == p)
{
T = p->rChild->lChild;
l = T->lChild;
r = T->rChild;
T->lChild = p;
T->rChild = p->rChild;
T->lChild->rChild = l;
T->rChild->lChild = r;
}
else
{
if (f->rChild == p)
{
f->rChild = p->rChild->lChild;
l = f->rChild->lChild;
r = f->rChild->rChild;
f->rChild->lChild = p;
f->rChild->rChild = p->rChild;
f->rChild->lChild->rChild = l;
f->rChild->rChild->lChild = r;
}
if (f->lChild == p)
{
f->lChild = p->rChild->lChild;
l = f->lChild->lChild;
r = f->lChild->rChild;
f->lChild->lChild = p;
f->lChild->rChild = p->rChild;
f->lChild->lChild->rChild = l;
f->lChild->rChild->lChild = r;
}
}
}
template<class DataType>
void AVLTree<DataType>::AllAdjust(Node < DataType>*& T)
{
//調(diào)整AVL
Node<DataType>* f = nullptr, * p = nullptr;
factorForTree(T);
nodeFactorIsTwoFather(T, f);
nodeFactorIsTwo(T, p);
while (p)
{
factorForTree(T);
if (p->balanceFactor == 2 && (p->lChild->balanceFactor == 1 || p->lChild->balanceFactor == 0))
{
LLAdjust(T, p, f);
factorForTree(T);
}
else if (p->balanceFactor == 2 && p->lChild->balanceFactor == -1)
{
LRAdjust(T, p, f);
factorForTree(T);
}
else if (p->balanceFactor == -2 && p->rChild->balanceFactor == 1)
{
RLAdjust(T, p, f);
factorForTree(T);
}
else if (p->balanceFactor == -2 && (p->rChild->balanceFactor == -1 || p->rChild->balanceFactor == 0))
{
RRAdjust(T, p, f);
}
f = nullptr;
p = nullptr;
nodeFactorIsTwoFather(T, f);
nodeFactorIsTwo(T, p);
}
}
template<class DataType>
int AVLTree<DataType>::BiTreeDepth(Node<DataType>* T)
{
//求樹(shù)的高度
int m, n;
if (T == nullptr)
{
return 0;
}
else {
m = BiTreeDepth(T->lChild);
n = BiTreeDepth(T->rChild);
if (m > n)
{
return m + 1;
}
else {
return n + 1;
}
}
}
template<class DataType>
int AVLTree<DataType>::getNodeFactor(Node < DataType>* T)
{
//求結(jié)點(diǎn)平衡因子
int m = 0, n = 0;
if (T)
{
m = BiTreeDepth(T->lChild);
n = BiTreeDepth(T->rChild);
}
return m - n;
}
template<class DataType>
void AVLTree<DataType>::factorForTree(Node<DataType>*& T)
{
//求樹(shù)的平衡因子
if (T)
{
T->balanceFactor = getNodeFactor(T);
factorForTree(T->lChild);
factorForTree(T->rChild);
}
}
template<class DataType>
void AVLTree<DataType>::nodeFactorIsTwo(Node<DataType>*& T, Node<DataType>*& p)
{
//獲得平衡因子為2或-2的節(jié)點(diǎn)
if (T)
{
if (T->balanceFactor == 2 || T->balanceFactor == -2)
{
p = T;
}
nodeFactorIsTwo(T->lChild, p);
nodeFactorIsTwo(T->rChild, p);
}
}
template<class DataType>
void AVLTree<DataType>::nodeFactorIsTwoFather(Node<DataType>*& T, Node<DataType>*& f)
{
//獲得平衡因子為2或-2的節(jié)點(diǎn)的父節(jié)點(diǎn)
if (T)
{
if (T->lChild != nullptr)
{
if (T->lChild->balanceFactor == 2 || T->lChild->balanceFactor == -2)
{
f = T;
}
}
if (T->rChild != nullptr)
{
if (T->rChild->balanceFactor == 2 || T->rChild->balanceFactor == -2)
{
f = T;
}
}
nodeFactorIsTwoFather(T->lChild, f);
nodeFactorIsTwoFather(T->rChild, f);
}
}
template<class DataType>
Node<DataType>* AVLTree<DataType>::getElementFatherPointer(Node <DataType>*& T, Node <DataType>*& f, DataType x)
{
//獲取父指針
if (T)
{
if (T->lChild != nullptr)
{
if (T->lChild->data == x)
f = T;
}
if (T->rChild != nullptr)
{
if (T->rChild->data == x)
f = T;
}
getElementFatherPointer(T->lChild, f, x);
getElementFatherPointer(T->rChild, f, x);
}
}
template<class DataType>
void AVLTree<DataType>::search(Node<DataType>*& T, Node<DataType>*& p, DataType x)
{
// 查找元素
if (T)
{
if (T->data == x)
{
p = T;
}
search(T->lChild, p, x);
search(T->rChild, p, x);
}
}
template<class DataType>
void AVLTree<DataType>::preOrderTraverse(Node<DataType>* T, int level)
{
//先序遍歷輸出
if (T)
{
cout << "先序遍歷" << "(" << T->data << "," << level << ")" << " ";
preOrderTraverse(T->lChild, level + 1);
preOrderTraverse(T->rChild, level + 1);
}
}





