内容:表(包括数组,链表,栈,队列)
参考文献:《数据结构与算法分析----C++语言描述(第四版)》
目的:希望各路大神指点一下
C++标准:C++11
操作系统:Ubuntu 18.04
编辑器:vs code
编译器:GCC 7.5.0
编译工具:CMake
二叉查找树(AVL)
#include <algorithm>
#include <iostream>
namespace my
{
static const int ALLOWED_IMBALANCE = 1;
template <typename>
class BinarySearchTree;
}
template <typename T>
std::ostream &operator<<(std::ostream &, const my::BinarySearchTree<T> &); //要先声明运算符重载
namespace my
{
template <typename T>
class BinarySearchTree
{
//要将模板函数声明为友元, 则必须在函数名后面加上类型<T>, 不然会报错
friend std::ostream &operator<<<T>(std::ostream &, const BinarySearchTree<T> &);
public:
BinarySearchTree() : root(nullptr) {}
BinarySearchTree(const BinarySearchTree &rhs) : root(clone(rhs.root)) {}
BinarySearchTree(BinarySearchTree &&rhs) : root(rhs.root) { rhs.root = nullptr; }
BinarySearchTree &operator=(const BinarySearchTree &);
BinarySearchTree &operator=(BinarySearchTree &&);
~BinarySearchTree() { clear(); }
const T &find_max() const { return find_max(root)->data; }
const T &find_min() const { return find_min(root)->data; }
bool contains(const T &x) const { return contains(x, root); }
bool empty() const { return root == nullptr; }
void clear() { clear(root); }
void insert(const T &x) { insert(x, root); }
void insert(T &&x) { insert(x, root); }
void remove(const T &x) { remove(x, root); }
private:
struct TreeNode
{
T data;
TreeNode *left;
TreeNode *right;
int height;
TreeNode(const T &d, TreeNode *l, TreeNode *r, int h)
: data(d), left(l), right(r), height(h) {}
TreeNode(T &&d, TreeNode *l, TreeNode *r, int h)
: data(std::move(d)), left(l), right(r), height(h) {}
};
TreeNode *root;
void insert(const T &, TreeNode *&); //指针的引用, 可以修改指针的值
void insert(T &&, TreeNode *&);
int height(TreeNode *t) const { return t == nullptr ? -1 : t->height; }
void rotate_with_left_child(TreeNode *&);
void double_rotate_with_left_child(TreeNode *&);
void rotate_with_right_child(TreeNode *&);
void double_rotate_with_right_child(TreeNode *&);
void remove(const T &, TreeNode *&);
void balance(TreeNode *&);
TreeNode *find_max(TreeNode *) const;
TreeNode *find_min(TreeNode *) const;
bool contains(const T &, TreeNode *) const;
void clear(TreeNode *&);
TreeNode *clone(TreeNode *t) const
{
if (t == nullptr)
return nullptr;
else
return new TreeNode(t->data, clone(t->left), clone(t->right), t->height);
}
void print(TreeNode *t, std::ostream &out) const
{
if (t != nullptr)
{
print(t->left, out);
out << t->data << " ";
print(t->right, out);
}
}
};
} // namespace my
template <typename T>
std::ostream &operator<<(std::ostream &out, const my::BinarySearchTree<T> &tree)
{
if (tree.empty())
{
out << "Empty tree";
}
else
{
tree.print(tree.root, out);
}
out << std::endl;
}
template <typename T>
bool my::BinarySearchTree<T>::contains(const T &x, TreeNode *t) const
{
if (t == nullptr)
return false;
else if (x < t->data)
return contains(x, t->left);
else if (t->data < x) //保证只用<, 而不用>
return contains(x, t->right);
else
return true;
}
template <typename T>
typename my::BinarySearchTree<T>::TreeNode *my::BinarySearchTree<T>::find_min(
my::BinarySearchTree<T>::TreeNode *t) const
//递归版
{
if (t == nullptr)
return nullptr;
if (t->left == nullptr)
return t;
return find_min(t->left);
}
template <typename T>
typename my::BinarySearchTree<T>::TreeNode *my::BinarySearchTree<T>::find_max(
my::BinarySearchTree<T>::TreeNode *t) const
{
//循环版
if (t != nullptr)
while (t->right != nullptr)
{
t = t->right;
}
return t;
}
template <typename T>
void my::BinarySearchTree<T>::insert(const T &x, TreeNode *&t)
{
if (t == nullptr)
t = new TreeNode(x, nullptr, nullptr, 0);
else if (x < t->data)
insert(x, t->left);
else if (t->data < x)
insert(x, t->right);
else
; // TODO:重复元素
balance(t);
}
template <typename T>
void my::BinarySearchTree<T>::insert(T &&x, TreeNode *&t)
{
if (t == nullptr)
t = new TreeNode(std::move(x), nullptr, nullptr);
else if (x < t->data)
insert(std::move(x), t->left);
else if (t->data < x)
insert(std::move(x), t->right);
else
; // TODO:重复元素
balance(t);
}
template <typename T>
void my::BinarySearchTree<T>::balance(TreeNode *&t)
{
if (t == nullptr)
return;
if (height(t->left) - height(t->right) > ALLOWED_IMBALANCE) //左边高于右边
{
if (height(t->left->left) >=
height(t->left->right)) //>=而不是>, 保证p127中, 删除情况下的情形
{
rotate_with_left_child(t);
}
else
{
double_rotate_with_left_child(t);
}
}
if (height(t->right) - height(t->left) > ALLOWED_IMBALANCE)
{
if (height(t->right->right) >= height(t->right->left))
{
rotate_with_right_child(t);
}
else
{
double_rotate_with_right_child(t);
}
}
t->height = std::max(height(t->left), height(t->right)) + 1;
}
template <typename T>
void my::BinarySearchTree<T>::rotate_with_left_child(TreeNode *&t)
{
TreeNode *k1 = t->left;
t->left = k1->right;
k1->right = t;
t->height = std::max(height(t->left), height(t->right)) + 1;
k1->height = std::max(height(k1->left), t->height) + 1;
t = k1;
}
template <typename T>
void my::BinarySearchTree<T>::rotate_with_right_child(TreeNode *&t)
{
TreeNode *k1 = t->right;
t->right = k1->left;
k1->left = t;
t->height = std::max(height(t->left), height(t->right)) + 1;
k1->height = std::max(height(k1->right), t->height) + 1;
t = k1;
}
template <typename T>
void my::BinarySearchTree<T>::double_rotate_with_left_child(TreeNode *&t)
{
rotate_with_right_child(t->left);
rotate_with_left_child(t);
}
template <typename T>
void my::BinarySearchTree<T>::double_rotate_with_right_child(TreeNode *&t)
{
rotate_with_left_child(t->right);
rotate_with_right_child(t);
}
template <typename T>
void my::BinarySearchTree<T>::remove(const T &x, TreeNode *&t)
{
if (t == nullptr) // x不在树t中
return;
if (x < t->data) // x在左边
remove(x, t->left);
else if (t->data < x) // x在右边
remove(x, t->right);
else if (t->left != nullptr && t->right != nullptr) //左右都是孩子
{
t->data = find_min(t->right)->data;
remove(t->data, t->right);
}
else //左右两边至少有一个nullptr
{
TreeNode *old = t;
//若左边不空, 左边顶上, 左边空的, 右边顶上, 两边都空, 直接没了
t = (t->left != nullptr) ? t->left : t->right;
delete old;
}
balance(t);
}
template <typename T>
void my::BinarySearchTree<T>::clear(TreeNode *&t)
{
if (t != nullptr)
{
clear(t->left);
clear(t->right);
delete t;
t = nullptr;
}
}
using namespace std;
int main(int argc, char const *argv[])
{
my::BinarySearchTree<int> tree;
for (int i = 0; i != 10; ++i)
{
tree.insert(i);
}
cout << tree << endl;
cout << "max: " << tree.find_max() << endl
<< "min: " << tree.find_min() << endl;
if (!tree.empty() && tree.contains(5))
{
cout << "tree contains 5." << endl;
tree.clear();
}
if (tree.empty())
cout << "Empty tree" << endl;
return 0;
}