二叉樹的遍歷

二叉樹的遍歷包括先序遍歷,中序遍歷,後序遍歷,層次遍歷等等。本文對此進行整理。

二叉樹結構定義如下:

//Definition for binary tree
struct TreeNode {
      int val;
      TreeNode *left;
      TreeNode *right;
      TreeNode(int x) : val(x), left(NULL), right(NULL) {}
  };
 

1. 先序遍歷

先序遍歷就是先訪問根節點,然後再先序遍歷左子樹,最後先序遍歷右子樹。先序遍歷也就是深度優先搜索(DFS)。

先序遍歷遞歸實現:

vector<int> preorderTraversal(TreeNode *root)
{
	vector<int> vals;
	preorderTraversal(root, vals);
	return vals;
}
void preorderTraversal(TreeNode *root, vector<int> &vals)
{
	if(root == NULL) return;
	vals.push_back(root->val);
	preorderTraversal(root->left, vals);
	preorderTraversal(root->right, vals);
}

先序遍歷非遞歸實現:

vector<int> preorderTraversal(TreeNode * root)
{
	vector<int> vals;
	stack<TreeNode*> s;
	TreeNode * p = root;
	while(!s.empty() || p)
	{
		if(p == NULL)
		{
			while(!s.empty() && (p == s.top()->right || s.top()->right == NULL)) 
			{	// 右子樹已訪問,出棧
				p = s.top();
				s.pop();
			}
			if(s.empty()) break;
			// 左子樹已訪問,右子樹尚未訪問,訪問右子樹
			p = s.top()->right;
		}
		else
		{
			vals.push_back(p->val);
			s.push(p);
			p = p->left;
		}
	}
	return vals;
}

2. 中序遍歷

中序遍歷就是先中序遍歷左子樹,然後訪問根節點,最後中序遍歷右子樹。

中序遍歷遞歸實現:

vector<int> inorderTraversal(TreeNode *root) 
{
	vector<int> vals;
	inorderTraversal(root, vals);
	return vals;
}
void inorderTraversal(TreeNode *root, vector<int> &vals)
{
	if(root == NULL) return;
	inorderTraversal(root->left, vals);
	vals.push_back(root->val);
	inorderTraversal(root->right, vals);
}
中序遍歷非遞歸實現:

vector<int> inorderTraversal(TreeNode *root) {
	vector<int> vals;
	stack<TreeNode *> s;
	TreeNode *p = root;
	while(!s.empty() || p)
	{
		while(p)
		{
			s.push(p);
			p = p->left;
		}
		p = s.top();
		s.pop();
		vals.push_back(p->val);
		p = p->right;
	}
	return vals;
}
3. 後序遍歷

後序遍歷就是先後序遍歷左子樹,再後序遍歷右子樹,最後訪問根節點。

後序遍歷遞歸實現:

vector<int> postorderTraversal(TreeNode* root)
{
	vector<int> vals;
	postorderTraversal(root, vals);
	return vals;
}
void postorderTraversal(TreeNode *root, vector<int> &vals)
{
	if(root == NULL)
		return;
	postorderTraversal(root->left, vals);
	postorderTraversal(root->right, vals);
	vals.push_back(root->val);
}

後序遍歷非遞歸實現:

vector<int> postorderTraversal(TreeNode* root)
{
	vector<int> vals;
	stack<TreeNode*> s;
	TreeNode * pre = NULL;
	TreeNode * p = root;
	while(!s.empty() || p)
	{
		while(p)
		{
			s.push(p);
			p = p->left;
		}
		pre = NULL;
		while(!s.empty() && pre == s.top()->right)
		{
			pre = s.top();
			vals.push_back(s.top()->val);
			s.pop();
		}
		if(s.empty()) break;
		p = s.top()->right;
	}
	return vals;
}
4. 層次遍歷

層次遍歷就是先遍歷第一層節點,然後遍歷第二層節點,。。。也就是廣度優先搜索(BFS)。

隊列實現:

vector<int> levelOrderTraversal(TreeNode *root) 
{
	vector<int> vals;
	if(root == NULL) 
		return vals;
	queue<TreeNode*> q;
	q.push(root);
	while(!q.empty())
	{
		TreeNode * p = q.front();
		q.pop();
		vals.push_back(p->val);
		if(p->left)
			q.push(p->left);
		if(p->right)
			q.push(p->right);
	}
	return vals;
}
層次遍歷遞歸實現:

vector<int> levelOrderTraversal(TreeNode *root) 
{
	vector<int> vals;
	height = getTreeHeight(root);
	for(int level = 1; level <= height; level++)
		levelOrderTraversal(root, level, vals);
	return vals;
}
int getTreeHeight(TreeNode * root)
{
	if(root == NULL) return 0;
	int heightLeft = getTreeHeight(root->left);
	int heightRight = getTreeHeight(root->right);
	return max(heightLeft, heightRight)+1;
}
void levelOrderTraversal(TreeNdoe *root, int level, vector<int> &vals)
{
	if(root == NULL) return;
	if(level == 1)
	{
		vals.push_back(root->val);
		return;
	}
	levelOrderTraversal(root->left, level-1, vals);
	levelOrderTraversal(root->right, level-1, vals);
}
注意,此實現時間複雜度仍然爲O(n).

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章