总结
-
remove不在BinNode里,而是BinTree里
-
递归的两种写法
从上往下:同一对象的递归(参数多一个,判空用一句话),子对象的递归(参数void,判空用两句话)(因为分叉,所以递归是真递归)
从下往上:不分叉,为了效率,可以用循环
// 我的最初写法(递归更新一条路径上的全部节点high值)
template <typename T>
void BinNode<T>::updateHigh(void)
{
int oldHigh = high;
high = std::max(getHigh(left), getHigh(right)) + 1;
if (parent != NULL && oldHigh != high) parent->updateHigh();
}
// 调用
rt->updateHigh();
// 改良版(循环更新一条路径上的全部节点high值)
template <typename T>
void BinTree<T>::updateHighAbove(BinNode<T> * rt)
{
while (rt)
{
if (!rt->updateHigh()) break; //这是书里说的优化,但书中并未实现
rt = rt->parent;
}
}
template <typename T>
bool BinNode<T>::updateHigh(void) //返回是否更新了树高
{
int oldHigh = high;
high = std::max(getHigh(left), getHigh(right)) + 1;
return oldHigh != high;
}
// 调用
updateHighAbove(rt);
-
整棵树与根节点的区别:整棵树的类型是BinTree 而根节点的类型是BinNode。二者都有成员变量high和size改了根节点的size,没改整棵树的size
-
发现high也有上一条的问题。书上BinTree没有设置high,BinNode没有size,那就删掉,省的单独更新
-
为什么remove写两个,因为
切断来自parent的指针
和更新高度
不用层层进行,还是为了提高效率。remove_core负责递归,remove在最外层负责切断来自parent的指针
和更新高度
code BinNode
# pragma once
# include <algorithm>
# define getHigh(x) x ? x->high : -1
// 仿函数:打印功能
template <typename T>
struct print {
void operator ()(T data)
{
std::cout << data << std::endl;
}
};
template <typename T>
struct BinNode {
int high;
T data;
BinNode<T> * left;
BinNode<T> * right;
BinNode<T> * parent;
int Size(BinNode<T> * x)
{
if (x)
{
return 1 + Size(x->left) + Size(x->right);
}
return 0;
}
BinNode(T const & d, BinNode<T> * p) : data(d), parent(p), left(NULL), right(NULL), size(1), high(0) {
}
BinNode<T> * insertAsLeft(T const & val)
{
left = new BinNode<T>(val, this);
return left;
}
BinNode<T> * insertAsRight(T const & val)
{
right = new BinNode<T>(val, this);
return right;
}
bool updateHigh(void)
{
int oldHigh = high;
high = std::max(getHigh(left), getHigh(right)) + 1;
return oldHigh != high;
//if (parent != NULL && oldHigh != high) parent->updateHigh();
}
template <typename T2>
void travPre(T2 visit)
{
visit(data);
if (left) left->travPre(visit);
if (right) right->travPre(visit);
}
template <typename T2>
void travIn(T2 visit)
{
if (left) left->travIn(visit);
visit(data);
if (right) right->travIn(visit);
}
template <typename T2>
void travPost(T2 visit)
{
if (left) left->travPost(visit);
if (right) right->travPost(visit);
visit(data);
}
};
code BinTree
# pragma once
# include "BinNode.h"
template <typename T>
class BinTree
{
protected:
public:
int size;
BinNode<T> * root;
public:
BinTree():size(0), root(NULL){
}
~BinTree() {
if (root) remove(root); }
//***********************************************************只读*********************************************************
int Size(void) const {
return size; }
bool empty(void) const {
return size == 0; }
BinNode<T> * Root(void) const {
return root; }
//***********************************************************可写*********************************************************
// 节点插入
BinNode<T> * insertAsRoot(T const & e)
{
size = 1;
root = new BinNode<T>(e, NULL);
return root;
}
BinNode<T> * insertAsLeft(T const & e, BinNode<T> * rt)
{
++size;
rt->insertAsLeft(e);
updateHighAbove(rt);
return rt->left;
}
BinNode<T> * insertAsRight(T const & e, BinNode<T> * rt)
{
++size;
rt->insertAsRight(e);
updateHighAbove(rt);
return rt->right;
}
// 子树接入,返回接入位置rt
BinNode<T> * attachAsLeft(BinTree<T> * newSubtree, BinNode<T> * rt)
{
size += newSubtree->size;
rt->left = newSubtree->root;
updateHighAbove(rt);
// 清空newSubtree原来的东西
newSubtree->size = 0;
newSubtree->root = NULL;
return rt;
}
BinNode<T> * attachAsRight(BinNode<T> * newSubtree, BinNode<T> * rt)
{
size += newSubtree->size;
rt->right = newSubtree->root;
updateHighAbove(rt);
// 清空newSubtree原来的东西
newSubtree->size = 0;
newSubtree->root = NULL;
return rt;
}
int remove(BinNode<T> * rt)
{
// 切断来自parent的指针
fromParentTo(rt) = NULL;
// 更新高度
updateHighAbove(rt->parent);
int ans = remove_core(BinNode<T> * rt);
size -= ans
return ans;
}
int remove_core(BinNode<T> * rt)
{
if (!rt) return 0; // 递归出口
int ans = remove(rt->left) + remove(rt->right) + 1;
delete rt;
return ans;
}
BinTree<T> * secede(BinNode<T> * rt) // 先不考虑 如果rt是树根
{
// 切断来自parent的指针
fromParentTo(rt) = NULL;
size -= BinNode<T>::Size(rt);
BinTree<T> * newTree = new BinTree<T>();
newTree->root = rt;
rt->parent = NULL;
updateHighAbove(rt->parent);
return newTree;
}
void updateHighAbove(BinNode<T> * rt)
{
while (rt)
{
if (!rt->updateHigh()) break;
rt = rt->parent;
}
}
//***********************************************************遍历*********************************************************
template <typename T2>
void travPre(T2 visit)
{
if (root) root->travPre(visit);
}
template <typename T2>
void travIn(T2 visit)
{
if (root) root->travIn(visit);
}
template <typename T2>
void travPost(T2 visit)
{
if (root) root->travPost(visit);
}
private:
BinNode<T> * & fromParentTo(BinNode<T> * x)
{
if (x == x->parent->left) return x->parent->left;
else return x->parent->right;
}
};