二叉树的非递归遍历——前序、中序、后序、层序、层序按行输出

二叉树的非递归遍历——前序、中序、后序、层序、层序按行输出

一、自己总结归纳的
二叉树的非递归遍历——前序、中序、后序、层序、层序按行输出

层序和前序的程序代码特别像,只有两点差别:
1、只是层序用到queue,前序用的stack
2、前序先push了右孩子,再push左孩子
层序先push了左孩子,再push右孩子

//层序遍历
void LevelOrder(BinaryTreeNode *T)
{
	if (T == NULL) return;
	queue<BinaryTreeNode *> Q;
	Q.push(T);//入队根指针
	while (!Q.empty()){
		BinaryTreeNode *cur = Q.front();
		Q.pop();
		cout << cur->data << " ";
		if (cur->lchild) Q.push(cur->lchild);
		if (cur->rchild) Q.push(cur->rchild);
	}
	cout << endl;
}
//前序遍历函数
void PreOrder(BinaryTreeNode *root)
{
	if (!root)return;
	stack<BinaryTreeNode *> S;
	S.push(root);
	while (!S.empty()){
		BinaryTreeNode* p = S.top();
		S.pop();
		cout << p->data << " ";
		if (p->rchild)S.push(p->rchild);
		if (p->lchild)S.push(p->lchild);
	}
	cout << endl;
}
//中序遍历
void inOrder(BinaryTreeNode *root){
	if (!root)return;
	stack<BinaryTreeNode *> S;
	while (!S.empty() || root){
		if (root){
			S.push(root);
			root = root->lchild;
		}
		else{
			root = S.top();
			S.pop();
			cout << root->data << " ";
			root = root->rchild;
		}
	}
	cout << endl;
}

//后序遍历
void postOrder(BinaryTreeNode *root){
	if (!root)return;
	stack<BinaryTreeNode *>S;
	BinaryTreeNode *pre = NULL, *cur = NULL;
	S.push(root);
	while (!S.empty()){
		cur = S.top();
		if ((!cur->lchild && !cur->rchild) || (pre && (pre == cur->lchild || pre == cur->rchild))){
			S.pop();
			cout << cur->data << " ";
			pre = cur;
		}
		else{
			if (cur->rchild)S.push(cur->rchild);
			if (cur->lchild)S.push(cur->lchild);
		}
	}
	cout << endl;
}

//层序遍历--按行输出
void LevelOrderByRow(BinaryTreeNode *root)
{
	if (!root) return;
	queue<BinaryTreeNode *> Q;
	Q.push(root);//入队根指针
	while (!Q.empty()){
		int count_row = Q.size();
		for (int i = 0; i < count_row; ++i){
			BinaryTreeNode *cur = Q.front();
			Q.pop();
			cout << cur->data << " ";
			if (cur->lchild) Q.push(cur->lchild);
			if (cur->rchild) Q.push(cur->rchild);
		}
		cout << endl;
	}
	cout << endl;
}

二、来自于昨夜的秋天**的二叉树的非递归遍历——前序、中序、后序

三种遍历的代码总体结构都是完全一样的,只是cout的时机有所不同。
都需要用一个stack来模拟递归时的函数调用。
对于三种遍历,我们都使用push当前节点->push左子树->pop左子树->push右子树->pop右子树的方式。

对于前序遍历来说,每次访问到一个节点就cout;

对于中序遍历来说,每次将右子节点进栈时,把当前节点cout;

对于后序遍历来说,每次pop的时候cout。

另外我们还需要一个last_pop指针来存放上一个pop出去的节点。

如果当前节点的左右节点都不是上一个pop的节点,那么我们将左子节点入栈;

如果当前节点的左节点是上一个pop的节点,但右节点不是,那么就把右子节点入栈;

否则的话,就需要让当前节点出栈。

void preorder_traversal_iteratively(BinaryTreeNode* root){
	if (root == 0)	return;
	stack<BinaryTreeNode*> s;
	s.push(root);
	cout << root->data << ' '; // visit root
	BinaryTreeNode* last_pop = root;
	while (!s.empty()){
		BinaryTreeNode* top = s.top();
		if (top->lchild != NULL && top->lchild != last_pop && top->rchild != last_pop){ // push_lchild
			s.push(top->lchild);
			cout << top->lchild->data << ' '; // visit top->lchild
		}
		else if (top->rchild != NULL && top->rchild != last_pop && (top->lchild == 0 || top->lchild == last_pop)){ // push_rchild
			s.push(top->rchild);
			cout << top->rchild->data << ' '; // visit top->rchild
		}
		else{ // pop
			s.pop();
			last_pop = top;
		}
	}
	cout << endl;
}

void inorder_traversal_iteratively(BinaryTreeNode* root){
	if (root == 0)	return;
	stack<BinaryTreeNode*> s;
	s.push(root);
	BinaryTreeNode* last_pop = root;
	while (!s.empty()){
		BinaryTreeNode* top = s.top();
		if (top->lchild != 0 && top->lchild != last_pop && top->rchild != last_pop){ // push_lchild
			s.push(top->lchild);
		}
		else if (top->rchild != 0 && top->rchild != last_pop && (top->lchild == 0 || top->lchild == last_pop)){ // push_rchild
			s.push(top->rchild);
			cout << top->data << ' '; // visit top
		}
		else{ // pop
			s.pop();
			last_pop = top;
			if (top->rchild == 0)
				cout << top->data << ' '; // visit top
		}
	}
	cout << endl;
}

void postorder_traversal_iteratively(BinaryTreeNode* root){
	if (root == 0)return;
	stack<BinaryTreeNode*> s;
	s.push(root);
	BinaryTreeNode* last_pop = root;
	while (!s.empty()){
		BinaryTreeNode* top = s.top();
		if (top->lchild != 0 && top->lchild != last_pop && top->rchild != last_pop){ // push_lchild
			s.push(top->lchild);
		}
		else if (top->rchild != 0 && top->rchild != last_pop && (top->lchild == 0 || top->lchild == last_pop)){ // push_rchild
			s.push(top->rchild);
		}
		else{ // pop
			s.pop();
			last_pop = top;
			cout << top->data << ' '; // visit top
		}
	}
	cout << endl;
}

实验的二叉树:

        1
      /   \
     2     3
   /   \     \
  4     5     6
       /  \
      7    8

实验代码:
其中的 ConstructBinaryTree()函数来自于我的另一篇博客C++ 使用数组建立二叉树 层序数组(方法二)

void test2(){
	cout << "by me" << endl;
	BinaryTreeNode *t;
	int data[] = { 1, 2, 3, 4, 5, '#', 6, '#', '#', 7, 8 };
	//前序遍历:1 2 4 5 7 8 3 6
	t = ConstructBinaryTree(data, sizeof(data) / sizeof(data[0]), 0);

	cout << "前序: ";
	PreOrder(t);

	cout << "中序: ";
	inOrder(t);

	cout << "后序: ";
	postOrder(t);

	cout << "层序: ";
	LevelOrder(t);

	cout << "层序--按行输出:" << endl;
	LevelOrderByRow(t);
}

void test3(){
	cout << "by 昨夜的秋天" << endl;
	BinaryTreeNode *t;
	int data[] = { 1, 2, 3, 4, 5, '#', 6, '#', '#', 7, 8 };
	//前序遍历:1 2 4 5 7 8 3 6
	t = ConstructBinaryTree(data, sizeof(data) / sizeof(data[0]), 0);

	cout << "前序: ";
	preorder_traversal_iteratively(t);

	cout << "中序: ";
	inorder_traversal_iteratively(t);

	cout << "后序: ";
	postorder_traversal_iteratively(t);
}
int main()
{
	test2();
	test3();
	cout << endl;
	return 0;
}

在这里插入图片描述

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值