/*
* 参考资料:
* <<算法导论>>, <<C算法: 第一卷>>
* 此程序经过大量测试, 测试类在 main.cpp文件中
* 类型 T 必须重载 < > == 比较运算符号
* 源码在: http://download.youkuaiyun.com/source/1712145
*/
#ifndef __BST_H_
#define __BST_H_
#include <iostream>
using namespace std;
template <class T>
struct _BST_Node
{
int n; // 记录子树的节点数
T key;
_BST_Node<T> *left;
_BST_Node<T> *right;
};
template <class T>
class BST
{
public :
typedef _BST_Node<T> BST_NODE;
typedef _BST_Node<T>* PBST_NODE;
BST();
~BST();
// 从底部插入
bool InsertNormal(const T& key);
// 从根部插入, 即每次插入的数据都在根部
bool InsertSpecial(const T& key);
// 找到则返回包含 key 的节点, 否则返回 0
PBST_NODE Find(const T& key) const;
// 统计 key 总共出现多少次
int Count(const T& key) const;
// 查找第 k 小数
T SelectKth(int kth) const;
// 删除键值等于 key 的键, 并返回删除的个数(0 or 1)
int EraseNormal(const T& key);
int EraseSpecial(const T& key);
// 查找 root 的后继节点, 如果不存在则返回 0
PBST_NODE Successor(PBST_NODE root) const;
// 查找 root 的前驱, 如果不存在则返回 0
PBST_NODE Vanguard(PBST_NODE root) const;
// 返回树的最小节点和最大节点值
T Min() const;
T Max() const;
// 把第 kth大节点提到根部, 也可以用于实现SelectKth(int kth), 但速度稍慢
void Partition(int kth);
PBST_NODE GetRoot() const { return m_pRoot; }
private :
// 删除树
void DestroyBST(PBST_NODE& root);
// 分配节点
PBST_NODE AllocateNode(const T& key);
// 释放节点 node 的内存
void DestroyNode(PBST_NODE& node);
// 插入操作, 辅助 bool Insert***(const T& key);
PBST_NODE InsertNormal(PBST_NODE root, const T& key);
PBST_NODE InsertSpecial(PBST_NODE root, const T& key);
// 左旋转
PBST_NODE LeftRotate(PBST_NODE root);
// 右旋转
PBST_NODE RightRotate(PBST_NODE root);
// 选择第 k 小数, 辅助 T SelectKth(int kth);
T __SelectKth(PBST_NODE root, int kth) const;
// 根为 root 的最大最小值节点
PBST_NODE Min(PBST_NODE root) const;
PBST_NODE Max(PBST_NODE root) const;
// 把第 kth 个数提到根部
PBST_NODE Partition(PBST_NODE root, int kth);
// 联合两棵有限制的二叉树, 即: rchild.Min() >= lchild.Max()
PBST_NODE Join(PBST_NODE lchild, PBST_NODE rchild);
// 删除操作, 辅助Erase***(const T& key);
PBST_NODE EraseNormal(PBST_NODE root, const T& key);
PBST_NODE EraseSpecial(PBST_NODE root, const T& key);
// 统计 key 在树中出现的次数, 辅助 Count(const T& key);
int Count(PBST_NODE root, const T& key) const;
private :
PBST_NODE m_pRoot;
};