数据结构之BinaryTree(二叉树)的实现

总结

  1. remove不在BinNode里,而是BinTree里

  2. 递归的两种写法
    从上往下:同一对象的递归(参数多一个,判空用一句话),子对象的递归(参数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);
  1. 整棵树与根节点的区别:整棵树的类型是BinTree 而根节点的类型是BinNode。二者都有成员变量high和size改了根节点的size,没改整棵树的size

  2. 发现high也有上一条的问题。书上BinTree没有设置high,BinNode没有size,那就删掉,省的单独更新

  3. 为什么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;
	}
};

猜你喜欢

转载自blog.csdn.net/weixin_45339670/article/details/131861927