02 树的各种遍历(递归与非递归的先中后序遍历,层次遍历)

二叉树的前中后遍历,递归与非递归

struct TreeNode {
	int  val;
	TreeNode* left;
	TreeNode* right;
	TreeNode (int x):val(x),left(NULL),right(NULL){}

};

递归

先序遍历:

void PreOrderTraversal(TreeNode* root) {
	if (!root) {
		return;
	}
	cout << root->val << " ";
	PreOrderTraversal(root->left);
	PreOrderTraversal(root->right);
}

中序遍历

void InOrderTraversal(TreeNode* root) {
	if (!root) {
		return;
	}
	InOrderTraversal(root->left);
	cout << root->val << " ";
	InOrderTraversal(root->right);
}

后序遍历

void PostOrderTraversal(TreeNode* root) {
	if (!root) {
		return;
	}
	PostOrderTraversal(root->left);
	PostOrderTraversal(root->right);
	cout << root->val << " ";
}

这三个遍历大同小异,仅仅只是输出的位置不同而已。
对于新手如果做牛客或者力扣上面的题的话,你除了把函数与变量名字改了之外,在函数中定义一个 vector result, 然后将所有的输出换成 result.push_back(root->val),再加上return result;即可。

非递归方式

非递归的方式遍历主要是依靠栈实现:

先序遍历:

vector<int> PreOrderTra(TreeNode* root) {
	vector<int>result;
	if (root == NULL) return result;
	stack<TreeNode*>s;
	TreeNode* p = root;
	while (p != NULL || !s.empty()) {
		while (p != NULL) {			//遍历左子树
			result.push_back(p->val);
			s.push(p);				//把遍历的节点全部压栈。
			p = p->left;
		}
		if (!s.empty()) {
			p = s.top();	//得到栈顶内容
			s.pop();		//出栈
			p = p->right;	//指向右子节点,下一次循环时,就会先续遍历左子树
		}
	}
	return result;
}

中序遍历

vector<int> InOrderTra(TreeNode* root) {
	vector<int>result;
	if (root == NULL) return result;
	stack<TreeNode*>s;
	TreeNode* p = root;
	while (p != NULL || !s.empty()) {
		while (p != NULL) {			//遍历左子树			
			s.push(p);				//把遍历的节点全部压栈。
			p = p->left;
		}
		if (!s.empty()) {
			p = s.top();	//得到栈顶内容
			s.pop();		//出栈
			result.push_back(p->val);
			p = p->right;	//指向右子节点,下一次循环时,就会先续遍历左子树
		}
	}
	return result;
}

后序遍历

后序遍历和前面有所不同
后序遍历需要在遍历完左右子树之后再访问根节点。因此需要判断根节点的左右子树是否均被遍历过

可采用标记法,节点入栈时,配一个标志tag一同入栈(tag为0表示遍历左子树前的现场保护,tag为1表示遍历右子树前的现场保护)
首先将T和tag(为0)入栈,遍历左子树;返回后,修改栈顶tag为1,遍历右子树;最后访问根节点

struct TreeNode {
	int  val;
	int  tag;
	TreeNode* left;
	TreeNode* right;
	TreeNode (int x):val(x),tag(0),left(NULL),right(NULL){}

};
vector<int> PostOrderTra(TreeNode* root) {
	vector<int>result;
	if (root == NULL) return result;
	stack<TreeNode*>s;
	TreeNode* p = root;
	while (p != NULL || !s.empty()) {
		while (p != NULL) {			//遍历左子树			
			s.push(p);				//把遍历的节点全部压栈。
			p = p->left;
		}
		if (!s.empty()) {
			p = s.top();	//得到栈顶内容
			if (p->tag) {	//tag为1时
				result.push_back(p->val);
				s.pop();		//出栈
				p = NULL;		//第二次访问标志其柚子树已经遍历
			}
			else {
				p->tag = 1;		//修改tag为1
				p = p->right;	//指向右节点,下次遍历其左子树
			}
		}
	}
	return result;
}

//层次遍历
在这里插入图片描述

vector<int> LeveOrderTra(TreeNode* root) {
	vector<int>result;
	queue<TreeNode*>q;
	TreeNode* ptr = NULL;
	q.push(root);			//根节点入队
	while (!q.empty()) {	
		ptr = q.front();	//得到头结点
		q.pop();			
		result.push_back(ptr->val);	
		if (ptr->left != NULL) {	//当前节点存在左节点则左节点入队
			q.push(ptr->left);
		}
		if (ptr->right != NULL) {	//当前节点存在右节点则右节点入队
			q.push(ptr->right);
		}
	}
	return result;
}
发布了57 篇原创文章 · 获赞 28 · 访问量 4100

猜你喜欢

转载自blog.csdn.net/weixin_41747893/article/details/104785306