二叉树遍历实现

二叉树遍历方法:先序遍历、中序遍历、后序遍历、层序遍历。

已知先序遍历序列中序遍历序列,可以唯一确定一颗二叉树
已知中序遍历序列后序遍历序列,可以唯一确定一颗二叉树
已知先序遍历序列后序遍历序列,不能唯一确定一颗二叉树

二叉树存储

  • 顺序存储:用一维数组存储二叉树中的节点,并且节点的存储位置,也就是数组的下标要能体现节点之间的逻辑关系,一般只用于完全二叉树 。
  • 链式存储:每个节点的结构具有一个存储数据的变量与两个指向孩子的指针域。

Node结构体

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

先序遍历(preorder traversal)

遍历顺序:根–左--右

//递归实现
void preorderRecursion(TreeNode* node, vector<int> &preorder) {
	preorder.push_back(node->val);
	if (node->left)
	{
		preorderRecursion(node->left, preorder);
	}
	if (node->right)
	{
		preorderRecursion(node->right, preorder);
	}
}

vector<int> preorderTraversal(TreeNode* root) {
	vector<int> preorder;
	if (root) 
	{
		preorderRecursion(root, preorder);
	}
	return preorder;
}
//迭代实现
vector<int> preorderTraversal(TreeNode* root) {
	vector<int> preorder;
	if (root)
	{
		stack<TreeNode*> toVisit;
		toVisit.push(root);
		while (!toVisit.empty())
		{
			TreeNode* visiting = toVisit.top();
			toVisit.pop();
			preorder.push_back(visiting->val);
			if (visiting->right)
			{
				toVisit.push(visiting->right);
			}
			if (visiting->left)
			{
				toVisit.push(visiting->left);
			}
		}
	}
	return preorder;
}

中序遍历(inorder traversal)

遍历顺序:左–根--右

//递归实现
void inorderRecursion(TreeNode* node, vector<int> &inorder) {
	if (node->left)
	{
		inorderRecursion(node->left, inorder);
	}
	inorder.push_back(node->val);
	if (node->right)
	{
		inorderRecursion(node->right, inorder);
	}
}

vector<int> inorderTraversal(TreeNode* root) {
	vector<int> inorder;
	if (root)
	{
		inorderRecursion(root, inorder);
	}
	return inorder;
}
//迭代实现
vector<int> inorderTraversal(TreeNode* root) {
	vector<int> inorder;
	if (root)
	{
		stack<TreeNode*> toVisit;
		toVisit.push(root);
		TreeNode* visiting = root->left;
		while (visiting || !toVisit.empty())
		{
			while (visiting)
			{
				toVisit.push(visiting);
				visiting = visiting->left;
			}
			visiting = toVisit.top();
			toVisit.pop();
			inorder.push_back(visiting->val);
			visiting = visiting->right;
		}
	}
	return inorder;
}

后序遍历(postorder traversal)

遍历顺序:左–右--根

//递归实现
void postorderRecursion(TreeNode* node, vector<int> &postorder) {
	if (node->left)
	{
		postorderRecursion(node->left, postorder);
	}
	if (node->right)
	{
		postorderRecursion(node->right, postorder);
	}
	postorder.push_back(node->val);
}

vector<int> postorderTraversal(TreeNode* root) {
	vector<int> postorder;
	if (root) 
	{
		postorderRecursion(root, postorder);
	}
	return postorder;
}
//迭代实现1
vector<int> postorderTraversal(TreeNode* root) {
	vector<int> postorder;
	if (root)
	{
		stack<TreeNode*> toVisit;
		toVisit.push(root);
		TreeNode* visiting = root->left;
		TreeNode* lastPop = NULL;
		while (visiting || !toVisit.empty())
		{
			while (visiting)
			{
				toVisit.push(visiting);
				visiting = visiting->left;
			}
			visiting = toVisit.top();
			if (!visiting->right || visiting->right == lastPop)
			{
				toVisit.pop();
				postorder.push_back(visiting->val);
				lastPop = visiting;
				visiting = NULL;
			}
			else
			{
				visiting = visiting->right;
			}
		}
	}
	return postorder;
}
//迭代实现2(思路挺好,大大简化了迭代版后续遍历的实现,本质是先序遍历的过程,结果是后序遍历的结果)
vector<int> postorderTraversal(TreeNode* root) {
	vector<int> postorder;
	if (root)
	{
		stack<TreeNode*> toVisit;
		toVisit.push(root);
		while (!toVisit.empty())
		{
			TreeNode* visiting = toVisit.top();
			toVisit.pop();
			postorder.push_back(visiting->val);
			if (visiting->left)
			{
				toVisit.push(visiting->left);
			}
			if (visiting->right)
			{
				toVisit.push(visiting->right);
			}
		}
		reverse(postorder.begin(), postorder.end());
	}
	return postorder;
}

层序遍历(level traversal)

遍历顺序:从上到下,从左到右

vector<int> levelTraversal(TreeNode* root) {
	vector<int> level;
	if (root)
	{
		queue<TreeNode*> toVisit;
		toVisit.push(root);
		while (!toVisit.empty()) 
		{
			TreeNode* visiting = toVisit.front();
			toVisit.pop();
			if (visiting->left)
			{
				toVisit.push(visiting->left);
			}
			if (visiting->right)
			{
				toVisit.push(visiting->right);
			}
			level.push_back(visiting->val);
		}
	}
	return level;
}

效率问题

二叉树遍历效率(只讨论节点个数较多情况)

  • 递归方法的先序遍历、中序遍历、后序遍历运行效率基本相同;
  • 迭代方法的先序遍历、中序遍历、后序遍历运行效率也基本相同;
  • 递归方法效率高于迭代方法效率;
  • 层序遍历效率介于递归和迭代效率之间,更靠近迭代效率。

综上:个人推荐使用递归版(先序、中序、后序均可),实现简单且效率高。

参考文献

https://blog.csdn.net/wjwfighting/article/details/81670229
https://blog.csdn.net/na_beginning/article/details/62219224

猜你喜欢

转载自blog.csdn.net/qq_24309981/article/details/85275275
今日推荐