非递归前序,中序,后序遍历二叉树,层次遍历二叉树,递归前序,中序,后序遍历二叉树(C++实现)

本文详细介绍了二叉树的四种遍历方法:递归的前序、中序、后序遍历以及非递归的前序、中序、后序和层次遍历。每种遍历方法都有清晰的代码实现,包括如何使用栈和队列辅助遍历。这些方法对于理解和操作二叉树结构至关重要。
摘要由CSDN通过智能技术生成

一、递归遍历二叉树

1.前序遍历二叉树

/*递归前序遍历*/
void preRecursive(const T* t){
	if(t == nullptr) return;
	cout << t->val << " ";
	preRecursive(t->left);
	preRecursive(t->right);
}

2.中序遍历二叉树

/*递归中序遍历*/
void InorderRecursive(T* t){
	if(t == nullptr) return;
	InorderRecursive(t->left);
	cout << t->val << " ";
	InorderRecursive(t->right);
}

3.后序遍历二叉树

/*递归后序遍历*/
void PostRecursive(T* t){
	if(t == nullptr) return;
	PostRecursive(t->left);
	PostRecursive(t->right);
	cout << t->val << " ";
}

二、非递归遍历二叉树

1. 非递归前序遍历

/*非递归前序遍历*/
void preorderTraserval(T* t){
	if(t==nullptr) return;
	stack<T*> q; //需要借助一个进行递归遍历栈
    while(!q.empty()){
		q.pop();
	}
	T* p = t;
	while(p!=nullptr || !q.empty()){ //这里的判定条件很关键
		if(p!=nullptr){
			cout << p->val << " "; //因为是前序,所以直接读
			q.push(p);
			p = p->left;
		}else{
			p = q.top();
			q.pop();
			p = p->right;
		}
	}
	cout << endl;
}

2. 非递归中序遍历

/*非递归中序遍历*/
void inorderTraserval(T* t){
	stack<T*>q;
	while(!q.empty()){
		q.pop();
	}
	T* p = t;
	while(p!=nullptr || !q.empty()){
		if(p!=nullptr){
			q.push(p);
			p = p->left;//先沿着左子树把节点入栈
		}else{
			p = q.top();//当前节点的左子树为空,则把遍历指针p指向栈顶节点
			cout << p->val << " ";//因为是中序遍历,所以此时读取节点的val
			q.pop();//将遍历过的节点弹出栈
			p = p->right;//继续遍历右子树
		}
	}
	cout << endl;
}

3. 非递归后序遍历

非递归后序遍历是这些遍历算法当中最复杂的一个

void postorderTraserval(T* t){
	stack<T*>q;//需要借助一个栈进行构建
	while(!q.empty())q.pop();
	T* p = t;
	T* pre;//需要记录上一个访问的节点,后面会有用
	while(p!=nullptr || !q.empty()){
		if(p!=nullptr){
			q.push(p);
			p = p->left; //和中序遍历相同,先把左节点都入栈
		}else{
			T* temp = q.top();//此时左节点为空,按照后序遍历的顺序,应该遍历右节点
			if(temp->right!=nullptr && temp->right!=pre){
				p = temp->right;//如果右节点不为空且右节点之前未访问过,则向右遍历
			}else{
                /*
                这里有两种情况:
                1. 当前栈顶节点的右节点为空,则该节点就是叶子节点,已经遍历到底,所以直接访问该元素;
                2. 当前栈顶节点的右节点是pre,也就是刚刚访问过的那个节点,也就是说当前节点的右子树已经访问过了,那么按照后序遍历顺序,该节点的左右子树都已访问过,那么接下来应该访问该节点;
                */
				cout << temp->val <<" ";
				q.pop();
				pre = temp;
				p = nullptr;
			}
		}
	}	
}

4. 层次遍历二叉树

/*层次遍历*/
void layerTraserval(T* t){
	if(t == nullptr) return;
	queue<T*> q; //层次遍历需要利用一个队列
	while(!q.empty())q.pop();
	q.push(t);
	T* temp;
	while(!q.empty()){
		temp = q.front();
		q.pop();
		cout << temp->val << " ";
		if(temp->left!=nullptr){
			q.push(temp->left);
		}
		if(temp->right!=nullptr){
			q.push(temp->right);
		}
	}
	cout <<endl;
	return;
}

三、完整代码

#include <iostream>
#include <queue>
#include <stack>
#include <string>
using namespace std;

typedef struct TreeNode{
	int val;
	TreeNode* left;
	TreeNode* right;
	TreeNode():val(0),left(nullptr),right(nullptr){};
	TreeNode(int x):val(x),left(nullptr),right(nullptr){};
}T;

void InorderCreateTree(T*& t){ //前序构建二叉树
	string x;
	cin >> x;
	if(x[0] == '#'){
		t = nullptr;
	}else{
		t = new T;
		t->val = stoi(x);
		InorderCreateTree(t->left);
		InorderCreateTree(t->right); 
	}
	return;
}

void layerCreateTree(T* &t){ //层次顺序构建二叉树
	string x;
	cin >> x;
	queue<T*> q;
	while(!q.empty())q.pop();
	if(x[0] == '#'){
		t = NULL;
		return; 
	}else{
		t = new T;
		t->val = stoi(x);
		q.push(t);
	}
	T* temp;
	while(!q.empty()){
		temp = q.front();
		if(temp == nullptr) continue;
		q.pop();
		cin >> x; 
		if(x[0] == '#'){
			temp->left = nullptr;
		}else{
			temp->left = new T;
			temp->left->val = stoi(x);
			q.push(temp->left);
		}
		cin >> x;
		if(x[0] == '#'){
			temp->right = nullptr;
		}else{
			temp->right = new T;
			temp->right->val = stoi(x);
			q.push(temp->right);
		}
	}
	return;
}

/*递归前序遍历*/
void preRecursive(const T* t){
	if(t == nullptr) return;
	cout << t->val << " ";
	preRecursive(t->left);
	preRecursive(t->right);
}

/*递归中序遍历*/
void InorderRecursive(T* t){
	if(t == nullptr) return;
	InorderRecursive(t->left);
	cout << t->val << " ";
	InorderRecursive(t->right);
}

/*递归后序遍历*/
void PostRecursive(T* t){
	if(t == nullptr) return;
	PostRecursive(t->left);
	PostRecursive(t->right);
	cout << t->val << " ";
}

/*非递归前序遍历*/
void preorderTraserval(T* t){
	if(t==nullptr) return;
	stack<T*> q;
	T* p = t;
	while(p!=nullptr || !q.empty()){
		if(p!=nullptr){
			cout << p->val << " ";
			q.push(p);
			p = p->left;
		}else{
			p = q.top();
			q.pop();
			p = p->right;
		}
	}
	cout << endl;
}

/*非递归中序遍历*/
void inorderTraserval(T* t){
	stack<T*>q;
	while(!q.empty()){
		q.pop();
	}
	T* p = t;
	while(p!=nullptr || !q.empty()){
		if(p!=nullptr){
			q.push(p);
			p = p->left;
		}else{
			p = q.top();
			cout << p->val << " ";
			q.pop();
			p = p->right;
		}
	}
	cout << endl;
}

/*非递归后序遍历*/
void postorderTraserval(T* t){
	stack<T*>q;
	while(!q.empty())q.pop();
	T* p = t;
	T* pre;
	while(p!=nullptr || !q.empty()){
		if(p!=nullptr){
			q.push(p);
			p = p->left; 
		}else{
			T* temp = q.top();
			if(temp->right!=nullptr && temp->right!=pre){
				p = temp->right;
			}else{
				cout << temp->val <<" ";
				q.pop();
				pre = temp;
				p = nullptr;
			}
		}
	}	
}

/*层次遍历*/
void layerTraserval(T* t){
	if(t == nullptr) return;
	queue<T*> q;
	while(!q.empty())q.pop();
	q.push(t);
	T* temp;
	while(!q.empty()){
		temp = q.front();
		q.pop();
		cout << temp->val << " ";
		if(temp->left!=nullptr){
			q.push(temp->left);
		}
		if(temp->right!=nullptr){
			q.push(temp->right);
		}
	}
	cout <<endl;
	return;
}

int main(){
	T* root;
	cout << "层次构建二叉树" << endl;
	//InorderCreateTree(root);
	layerCreateTree(root);
	cout << "树已经创建完毕!" << endl;
    
	cout<< "递归先序遍历" << endl;
	preRecursive(root);
	cout << endl;
	
	cout<< "递归中序遍历" << endl;
	InorderRecursive(root);	
	cout << endl;
	
	cout<< "递归后序遍历" << endl;
	PostRecursive(root);
	cout << endl;
	
	cout<< "非递归先序遍历" << endl;
	preorderTraserval(root);
	
	cout<< "非递归中序遍历" << endl;
	inorderTraserval(root);
	
	cout<< "非递归后序遍历" << endl;
	postorderTraserval(root);
	cout<<endl;
	
    cout << "层次遍历二叉树" <<endl;
	layerTraserval(root);
	return 0;
}

在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值