(十一)、C++ 平衡二叉树
#include <iostream>
#include <queue>
/**
* @namespace 平衡二叉树
*/
namespace tree_AVL
{
template<class T>
class Tree
{
public:
struct node
{
node(T m_pData) :m_Tdata(m_pData), m_left(nullptr), m_right(nullptr) {}
T m_Tdata;
node* m_left;
node* m_right;
};
Tree() :m_root(nullptr) {}
/**
* @brief 插入
* @param m_pData: 插入值
*/
void insert(T m_pData)
{
m_root = insert(m_root, m_pData);
}
/**
* @brief 删除
* @param m_pData: 删除值
*/
void remove(T m_pData)
{
m_root = remove(m_root, m_pData);
}
/**
* @brief 返回树的高度
*/
int height(node* m_pRoot)
{
if (m_pRoot == NULL)
return 0;
return 1 + std::max(height(m_pRoot->m_left), height(m_pRoot->m_right));
}
/**
* @brief 返回左右子树的高度差
*/
int getBalance(node* m_pRoot) { return height(m_pRoot->m_left) - height(m_pRoot->m_right); }
/**
* @brief 返回右旋转后的节点
*/
node* rightRotate(node* m_pRoot)
{
node* t = m_pRoot->m_left;
node* u = t->m_right;
t->m_right = m_pRoot;
m_pRoot->m_left = u;
return t;
}
/**
* @brief 返回左旋转后的节点
*/
node* leftRotate(node* m_pRoot)
{
node* t = m_pRoot->m_right;
node* u = t->m_left;
t->m_left = m_pRoot;
m_pRoot->m_right = u;
return t;
}
/**
* @brief 返回树中具有最小值的节点
*/
node* minValue(node* m_pRoot)
{
if (m_pRoot->m_left == NULL)
return m_pRoot;
return minValue(m_pRoot->m_left);
}
/**
* @brief 层次遍历
*/
void print_level()
{
std::queue<node*> queTree;
node* temp = m_root;
queTree.push(temp);
while (!queTree.empty())
{
temp = queTree.front();
std::cout << temp->m_Tdata << " ";
queTree.pop();
if (temp->m_left != nullptr)
queTree.push(temp->m_left);
if (temp->m_right != nullptr)
queTree.push(temp->m_right);
}
std::cout << std::endl;
}
private:
/**
* @brief 插入
* @param m_pRoot: 节点
* @param m_pData: 插入值
*/
node* insert(node* m_pRoot, T m_pData)
{
if (m_pRoot == NULL)
return new node(m_pData);
if (m_pData < m_pRoot->m_Tdata)
m_pRoot->m_left = insert(m_pRoot->m_left, m_pData);
else
m_pRoot->m_right = insert(m_pRoot->m_right, m_pData);
int b = getBalance(m_pRoot); // 平衡因子
if (b > 1) // 左子树失衡
{
if (getBalance(m_pRoot->m_left) < 0)
m_pRoot->m_left = leftRotate(m_pRoot->m_left); // Left-Right Case
return rightRotate(m_pRoot); // Left-Left Case
}
else if (b < -1) // 右子树失衡
{
if (getBalance(m_pRoot->m_right) > 0)
m_pRoot->m_right = rightRotate(m_pRoot->m_right); // Right-Left Case
return leftRotate(m_pRoot); // Right-Right Case
}
return m_pRoot;
}
/**
* @brief 删除
* @param m_pRoot: 节点
* @param m_pData: 删除值
*/
node* remove(node* m_pRoot, T m_pData)
{
if (m_pRoot == nullptr)
return m_pRoot;
if (m_pData < m_pRoot->m_Tdata) // 删除节点位于左子树
m_pRoot->m_left = remove(m_pRoot->m_left, m_pData);
else if (m_pData > m_pRoot->m_Tdata) // 删除节点位于右子树
m_pRoot->m_right = remove(m_pRoot->m_right, m_pData);
else // 找到该节点所在
{
if (m_pRoot->m_right == nullptr) // 要删除的节点是叶节点或只有一个子节点
{
node* temp = m_pRoot->m_left;
delete (m_pRoot);
m_pRoot = nullptr;
return temp;
}
else if (m_pRoot->m_left == nullptr)
{
node* temp = m_pRoot->m_right;
delete (m_pRoot);
m_pRoot = nullptr;
return temp;
}
// 要删除的节点同时具有左子树和右子树
node* temp = minValue(m_pRoot->m_right); // 找到右子树的最小节点
m_pRoot->m_Tdata = temp->m_Tdata; // 将最小节点的值赋值给找到的节点,然后去删除上一步找到的右子树的最小节点
m_pRoot->m_right = remove(m_pRoot->m_right, temp->m_Tdata);
}
// Balancing Tree after deletion
return m_pRoot;
}
private:
node* m_root;
};
void test_tree_AVL()
{
tree_AVL::Tree<int> m_tree;
m_tree.insert(1);
/*
(1)
*/
m_tree.insert(4);
/*
(1)
\
(4)
*/
m_tree.insert(3);
/*
(1) 平衡 (3)
\ =====> / \
(4) (1) (4)
/
(3)
*/
m_tree.insert(7);
/*
(3)
/ \
(1) (4)
\
(7)
*/
m_tree.insert(8);
/*
(3) (3)
/ \ / \
(1) (4) 平衡 (1) (7)
\ =====> / \
(7) (4) (8)
\
(8)
*/
m_tree.insert(2);
/*
(3) (3)
/ \ / \
(1) (7) 平衡 (1) (7)
/ \ =====> \ / \
(4) (8) (2) (4) (8)
*/
std::cout << "AVL 层次遍历(队列实现):";
m_tree.print_level(); // 3 1 7 2 4 8
std::cout << "AVL 删除(3):";
m_tree.remove(3);
/*
(3) (4)
/ \ / \
(1) (7) 删除(3) (1) (7)
\ / \ =====> \ \
(2) (4) (8) (2) (8)
*/
m_tree.print_level(); // 4 1 7 2 8
}
}// namespace tree_AVL
int main()
{
tree_AVL::test_tree_AVL();
return 0;
}