树结构及遍历算法

最近刚刚学完邓俊辉的数据结构中的二叉树结构,将自己所学记录下来,方便日后进行回顾。

#include <iostream>
#include <stack>
#include <queue>

#define BinNodePosi(T) BinNode<T>* //节点位置
#define stature(p) ((p) ? (p)->height : -1) //节点高度(与“空树高度为-1”的约定相统一)

using namespace std;

template <typename T> struct BinNode
{
    BinNodePosi(T) parent;
	BinNodePosi(T) lChild;
	BinNodePosi(T) rChild;//父亲 孩子
    T data;	//值
    int height;//高度
	int size();//子树规模(后代总数)

    // 构造函数
    BinNode():parent(NULL), lChild(NULL), rChild(NULL), height(0){}
    BinNode(T e, BinNodePosi(T) p = NULL, BinNodePosi(T) lc = NULL, BinNodePosi(T) rc = NULL, int h = 0):data(e), parent(p), lChild(lc), rChild(rc), height(h){};
    BinNodePosi(T) insertAsLC(T const &e);  //插入为左孩子
	BinNodePosi(T) insertAsRC(T const &e); //插入为右孩子
};

template<typename T> int BinNode<T>::size()
{
    int s = 1; //树首先会有一个根节点
    if (lChild) s += lChild->size(); //如果有左孩子的话, c++中定义类对象是指针对象时候,就需要用到->指向类中的成员
    if (rChild) s += rChild->size(); //如果有右孩子的话
    return s;
}

template <typename T> BinNodePosi(T) BinNode<T>::insertAsLC(T const &e)
{
    return lChild = new BinNode(e, this);
}

template <typename T> BinNodePosi(T) BinNode<T>::insertAsRC(T const &e)
{
    return rChild = new BinNode(e, this);
}

template<typename T>
class BinTree // 构建一个二叉树
{
    protected:
        int _size; //规模
        BinNodePosi(T) _root; // //根节点
        virtual int updateHeight(BinNodePosi(T) x); //更新节点x的高度
        void updateHeightAbove(BinNodePosi(T) x);//更新节点x及祖先的高度
    public:
        BinTree():_size(0), _root(NULL){}  //构造函数
	    ~BinTree(){if(0<_size) delete _root; }  //析构函数
        int size() const {return _size;} //规模
        bool empty() const {return !_root;} //判空
        BinNodePosi(T) root() const{return _root;} //树根	
        BinNodePosi(T) insertAsRoot(T const &e); //作为树根插入空树
        BinNodePosi(T) insertAsLC(BinNodePosi(T), T const &e); //作为左孩子插入
        BinNodePosi(T) insertAsRC(BinNodePosi(T), T const &e); //作为右孩子插入
        void travPre_a(BinNodePosi(T));//先序遍历(递归)
        void travPre_b(BinNodePosi(T));//先序遍历(迭代1)
        void visitAlongLeftBranch(BinNodePosi(T) x, stack<BinNodePosi(T)> &s);//一直遍历左孩子
        void visitAlongLeftBranch_In(BinNodePosi(T) x, stack<BinNodePosi(T)> &s);
        void travPre_c(BinNodePosi(T) x);//先序遍历(迭代2)
        void travIn(BinNodePosi(T) x);//中序遍历
        void travLevel(BinNodePosi(T) x);//层次遍历
};

template <typename T> BinNodePosi(T) BinTree<T>::insertAsRoot(T const& e)
{
	_size = 1;
	return _root = new BinNode<T> (e);
}

template<typename T> 
int BinTree<T>::updateHeight(BinNodePosi(T) x)
{
    return x -> height = 1 + max(stature(x->lChild), stature(x->rChild));
}

template<typename T>
void BinTree<T>::updateHeightAbove(BinNodePosi(T) x)
{
	while(x){
		updateHeight(x);
		x = x->parent;
	}
}

template<typename T>
BinNodePosi(T) BinTree<T>::insertAsLC(BinNodePosi(T) x, T const &e)
{
    _size++;
    x->insertAsLC(e);
	updateHeightAbove(x);
	return x->lChild;
}

template<typename T>
BinNodePosi(T) BinTree<T>::insertAsRC(BinNodePosi(T) x, T const &e) 
{
	_size++;
	x->insertAsRC(e);
	updateHeightAbove(x);
	return x->rChild;
}

// 先序遍历的递归版本
template<typename T>
void BinTree<T>::travPre_a(BinNodePosi(T) x)
{
	if(!x)return;
	cout<<x->data<<"\t";
	travPre_a(x->lChild);
	travPre_a(x->rChild);
}


// 先序遍历的迭代版本,分为两个阶段
//根据算法地理解为先将右孩子入栈,再将左孩子入栈,这样进行遍历就会线遍历左孩子
//同时将左支树遍历完之后再从下往上进行遍历
template<typename T>
void BinTree<T>::travPre_b(BinNodePosi(T) x)
{
	stack<BinNodePosi(T)> s;
	if(x) s.push(x);//根节点入栈
	while(!s.empty())
	{
		x = s.top();
		s.pop();
		cout<<x->data<<"\t";
		if(x->rChild)s.push(x->rChild);
		if(x->lChild)s.push(x->lChild);
	}
}

// 下面是迭代版本c
// 沿着最左侧通道自顶而下访问的个节点
//以及自底而上遍历的对应右子树
template<typename T>
void BinTree<T>::visitAlongLeftBranch(BinNodePosi(T) x, stack<BinNodePosi(T)> &s)
{
	while(x){
		cout<<x->data<<"\t";
		s.push(x->rChild);//右孩子入栈
		x = x->lChild;//沿左侧链下行
	}
}

template<typename T>
void BinTree<T>::travPre_c(BinNodePosi(T) x)
{
	stack<BinNodePosi(T)> S;
	while(true)
	{
		visitAlongLeftBranch(x, S);
		if(S.empty())break;
		x = S.top();
		S.pop();
	}
}


// 中序遍历
// 沿最左侧的通路自底而上,以沿途各节点为界
template<typename T>
void BinTree<T>::visitAlongLeftBranch_In(BinNodePosi(T) x, stack<BinNodePosi(T)> &s)
{
	while(x){
		s.push(x);//入栈
		x = x->lChild;//沿左侧链下行
	}
}

template<typename T>
void BinTree<T>::travIn(BinNodePosi(T) x)
{
	stack<BinNodePosi(T)> S;
	while(1)
	{
		visitAlongLeftBranch_In(x,S);
		if(S.empty())break;
		x=S.top();
		S.pop();
		cout<<x->data<<"\t";
		x = x->rChild;
	}
}

// 层次遍历
//先上后下,先左后右
template<typename T>
void BinTree<T>::travLevel(BinNodePosi(T) x)
{
	queue<BinNodePosi(T)> q;
	q.push(x);
	while(!q.empty())
	{
		BinNodePosi(T) x = q.front();
		q.pop();
		cout<<x->data<<"\t";
		if(x->lChild)q.push(x->lChild);
		if(x->rChild)q.push(x->rChild);
	}
}


int main()
{
	BinTree<int> BT;
	BT.insertAsRoot(3);
	BinNode<int>* a = BT.insertAsLC(BT.root(), 4);
	BT.insertAsLC(a, 6);
	BT.insertAsRC(a, 7);
	BT.insertAsRC(BT.root(), 5);
	BT.travPre_a(BT.root());
	cout<<endl;
	BT.travPre_b(BT.root());
	cout<<endl;
	BT.travPre_c(BT.root());
	cout<<endl;
	BT.travIn(BT.root());
	cout<<endl;
	BT.travLevel(BT.root());
	cout<<endl;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值