DSA学习笔记——二叉树之遍历

二叉树遍历作为二叉树中最重要的一部分内容,其主要目的在于:为所有节点赋予一个次序,从而将半线性的二叉树转化为线性结构。二叉树遍历算法的迭代版本有一个通用的思考思路:首先找到第一个访问的节点,找到跟节点到这个节点的唯一路径,然后将遍历过程划分为相同小过程。

1、先序遍历

递归版

template <typename T, typename VST>
void travPre_R(BinNode<T>* x, VST& visit){
	if(!x)	return;
	visit(x->data);
	travPre_R(x->lc, visit);
	travPre_R(x->rc, visit);
}

迭代版

template <typename T, typename VST>
static void visitAlongLeftBranch(BinNode<T>* x, VST& visit, Stack<BinNode<T>*>& S){
	while(x){
		visit(x->data);
		S.push(x->rc);
		x = x->lc;
	}
}

//先序遍历迭代版版本2代码
template <typename T, typename VST>
void travPre_I2(BinNode<T>* x, VST& visit){
	Stack<BinNode<T>*> S;
	while(true){
		visitAlongLeftBranch(x, visit, S);
		if(S.empty()) break;
		x = S.pop();
	}
}

2、中序遍历

中序遍历定位直接后继

template <typename T>
BinNode<T>* BinNode<T>::succ(){
	BinNode<T>* s = this;
	if(rc){
		s = rc;
		while( HasLChild(*s)) s = s->lc;
	}else{
		while(IsRChild(*s)) s = s->parent;
		s = s->parent;
	}
	return s;
}

递归版

template <typename T, typename VST>
void travIn_R(BinNode<T>* x, VST& visit){
	if(!x) return;
	travIn_R(x->lc, visit);
	visit(x->data);
	travIn_R(x->rc, visit);
}

迭代版

template <typename T>
static void goAlongLeftBranch(BinNode<T>* x, Stack<BinNode<T>*>& S){
	while(x){
		S.push(x);
		x = x->lc;
	}
}

//中序遍历迭代版版本1,借助辅助栈完成
template <typename T, typename VST>
void travIn_I1(BinNode<T>* x, VST& visit){
	Stack<BinNode<T>*> S;
	while(true){
		goAlongLeftBranch(x, S);
		if(S.empty()) break;
		x = S.pop();
		visit(x->data);
		x = x->rc;
	}
}
//中序遍历迭代版版本2,版本1的等价形式,借助该版本可以方便实现版本3
template <typename T, typename VST>
void travIn_I2(BinNode<T>* x, VST& visit){
	Stack<BinNode<T>*> S;
	while(true){
		if(x){
			S.push(x);
			x = x->lc;
		}else if(!S.empty()){
			x = S.pop();
			visit(x->data);
			x = x->rc;
		}else
			break;
	}
}
//中序遍历迭代版版本3,就地算法
template <typename T, typename VST>
void travIn_I3(BinNode<T>* x, VST& visit){
	bool backtrack = false;
	while(true){
		if(!backtrack && HasLChild(*x))
			x = x->lc;
		else{
			visit(x->data);
			if(HasRChild(*x)){
				x = x->rc;
				backtrack = false;
			}else{
				if(!(x = x->succ())) break;
				backtrack = true;
			}
		}
	}
}

3、后序遍历

递归版本

template <typename T, typename VST>
void travPost_R(BinNode<T>* x, &VST visit){
	if(!x) return;
	travPost_R(x->lc, visit);
	travPost_R(x->rc, visit);
	visit(x->data);
}

迭代版本

template <typename T>
static void gotoHLVFL(Stack<BinNode<T>*>& S){
	while(BinNode<T>* x = S.top())
		if(HasLChild(*x)){
			if(HasRChild(*x)) S.push(x->rc);
			S.push(x->lc);
		}else
			S.push(x->rc);
		S.pop();
}

template <typename T, typename VST>
void travPost_I(BinNode<T>* x, VST& visit){
	Stack<BinNode<T>*> S;
	if(x) S.push(x);
	while(!S.empty()){
		if(S.top() != x->parent)
			gotoHLVFL(S);
		x = S.pop(); visit(x->data);
	}
}

4、层次遍历

template <typename T, typename VST>
void BinNode<T>::travLevel(VST& visit){
	Queue<BinNode<T>*> Q;
	Q.enqueue(this);
	while(!Q.empty()){
		BinNode<T>* x = Q.dequeue(); visit(x->data);
		if(HasLChild(*x)) Q.enqueue(x->lc);
		if(HasRChild(*x)) Q.enqueue(x->rc);
	}
}
发布了17 篇原创文章 · 获赞 0 · 访问量 673

猜你喜欢

转载自blog.csdn.net/Nemoosi/article/details/104538646