二叉树的前序、中序和后序遍历

    来源:leetcode 二叉树的前序、中序和后序遍历

       

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

//栈 先序遍历
// LeetCode, Binary Tree Preorder Traversal
// 使用栈,时间复杂度O(n),空间复杂度O(n)

vector<int> preorderTraversal(TreeNode *root) 
{
	vector<int> result;
	const TreeNode *p;
	stack<const TreeNode *> s;
	p = root;
	if (p != nullptr) s.push(p);
	while (!s.empty()) 
	{
		p = s.top();
		s.pop();
		result.push_back(p->val);
		if (p->right != nullptr) s.push(p->right);
		if (p->left != nullptr) s.push(p->left);
	}
	return result;
}

//Morris 先序遍历
// LeetCode, Binary Tree Preorder Traversal
// Morris 先序遍历,时间复杂度O(n),空间复杂度O(1)

vector<int> preorderTraversal(TreeNode *root) 
{
	vector<int> result;
	TreeNode *cur, *prev;
	cur = root;
	while (cur != nullptr) {
		if (cur->left == nullptr) {
			result.push_back(cur->val);
			prev = cur; /* cur 刚刚被访问过*/
			cur = cur->right;
		}
		else 
		{
			/* 查找前驱*/
			TreeNode *node = cur->left;
			while (node->right != nullptr && node->right != cur)
				node = node->right;
			if (node->right == nullptr) 
			{ /* 还没线索化,则建立线索*/
				result.push_back(cur->val); /* 仅这一行的位置与中序不同*/
				node->right = cur;
				prev = cur; /* cur 刚刚被访问过*/
				cur = cur->left;
			} 
			else 
			{ /* 已经线索化,则删除线索*/
				node->right = nullptr;
				/* prev = cur; 不能有这句,cur 已经被访问*/
				cur = cur->right;
			}
		}
	}
	return result;
}

//栈 中序遍历
// LeetCode, Binary Tree Inorder Traversal
// 使用栈,时间复杂度O(n),空间复杂度O(n)

vector<int> inorderTraversal(TreeNode *root) 
{
	vector<int> result;
	const TreeNode *p = root;
	stack<const TreeNode *> s;
	while (!s.empty() || p != nullptr) 
	{
		if (p != nullptr) 
		{
			s.push(p);
			p = p->left;
		} 
		else 
		{
			p = s.top();
			s.pop();
			result.push_back(p->val);
			p = p->right;
		}
	}
	return result;
}

//Morris 中序遍历
// LeetCode, Binary Tree Inorder Traversal
// Morris 中序遍历,时间复杂度O(n),空间复杂度O(1)

vector<int> inorderTraversal(TreeNode *root) 
{
	vector<int> result;
	TreeNode *cur, *prev;
	cur = root;
	while (cur != nullptr)
	{
		if (cur->left == nullptr) 
		{
			result.push_back(cur->val);
			prev = cur;
			cur = cur->right;
		} else {
			/* 查找前驱*/
			TreeNode *node = cur->left;
			while (node->right != nullptr && node->right != cur)
				node = node->right;
			if (node->right == nullptr)
			{ /* 还没线索化,则建立线索*/
				node->right = cur;
				/* prev = cur; 不能有这句,cur 还没有被访问*/
				cur = cur->left;
			} 
			else 
			{ /* 已经线索化,则访问节点,并删除线索*/
				result.push_back(cur->val);
				node->right = nullptr;
				prev = cur;
				cur = cur->right;
			}
		}
	}
	return result;
}

//栈 后序遍历
// LeetCode, Binary Tree Postorder Traversal
// 使用栈,时间复杂度O(n),空间复杂度O(n)

vector<int> postorderTraversal(TreeNode *root) 
{
	vector<int> result;
	/* p,正在访问的结点,q,刚刚访问过的结点*/
	const TreeNode *p, *q;
	stack<const TreeNode *> s;
	p = root;
	do 
	{
		while (p != nullptr) 
		{ /* 往左下走*/
			s.push(p);
			p = p->left;
		}q
			= nullptr;
		while (!s.empty()) 
		{
			p = s.top();
			s.pop();
			/* 右孩子不存在或已被访问,访问之*/
			if (p->right == q) {
				result.push_back(p->val);
				q = p; /* 保存刚访问过的结点*/
			}
			else 
			{
				/* 当前结点不能访问,需第二次进栈*/
				s.push(p);
				/* 先处理右子树*/
				p = p->right;
				break;
			}
		}
	} while (!s.empty());
	return result;
}

//Morris 后序遍历
// LeetCode, Binary Tree Postorder Traversal
// Morris 后序遍历,时间复杂度O(n),空间复杂度O(1)
// LeetCode, Binary Tree Postorder Traversal
// Morris 后序遍历,时间复杂度O(n),空间复杂度O(1)
class Solution {
public:
	vector<int> postorderTraversal(TreeNode *root) {
		vector<int> result;
		TreeNode dummy(-1);
		TreeNode *cur, *prev = nullptr;
		std::function < void(const TreeNode*)> visit =
			[&result](const TreeNode *node){
				result.push_back(node->val);
		};
		dummy.left = root;
		cur = &dummy;
		while (cur != nullptr) {
			if (cur->left == nullptr) {
				prev = cur; /* 必须要有*/
				cur = cur->right;
			} else {
				TreeNode *node = cur->left;
				while (node->right != nullptr && node->right != cur)
					node = node->right;
				if (node->right == nullptr) { /* 还没线索化,则建立线索*/
					node->right = cur;
					prev = cur; /* 必须要有*/
					cur = cur->left;
				} else { /* 已经线索化,则访问节点,并删除线索*/
					visit_reverse(cur->left, prev, visit);
					prev->right = nullptr;
					prev = cur; /* 必须要有*/
					cur = cur->right;
				}
			}
		}
		return result;
	}
private:
	// 逆转路径
	static void reverse(TreeNode *from, TreeNode *to) {
		TreeNode *x = from, *y = from->right, *z;
		if (from == to) return;
		while (x != to) {
			z = y->right;
			y->right = x;
			x = y;
			y = z;
		}
	}
	// 访问逆转后的路径上的所有结点
	static void visit_reverse(TreeNode* from, TreeNode *to,
		std::function< void(const TreeNode*) >& visit) {
			TreeNode *p = to;
			reverse(from, to);
			while (true) {
				visit(p);
				if (p == from)
					break;
				p = p->right;
			}
			reverse(to, from);
	}
};
    

    测试代码:

TreeNode a[7];
	for (int i = 0; i <7; i++)
		a[i].val = i + 2;
	a[0].left = &a[1];
	a[0].right = &a[2];
	a[1].left = &a[3];
	a[1].right = &a[4];
	a[2].left = &a[5];
	a[2].right = &a[6];
	a[3].left = &a[1];
	a[3].right = &a[4];
	a[1].left = &a[0];
	a[1].right = &a[2];
	a[4].right = &a[5];
	a[5].right = &a[6];


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值