二叉树的遍历
二叉树节点的定义
1 2 3 4 5 6 7 8
| struct TreeNode { int val; TreeNode *left; TreeNode *right; TreeNode() : val(0), left(nullptr), right(nullptr) {} TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} };
|
前序遍历
递归实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| vector<int> preOrderTraversal(TreeNode* root) { vector<int> res; preOrder(root,res); return res; } void preOrder(TreeNode* root, vector<int> &res){ if (root == nullptr){ return; } res.push_back(root->val); preOrder(root->left,res); preOrder(root->right,res); }
|
非递归实现
当栈不为空时,栈顶元素出栈,如果其右子节点不为空,则右子节点入栈,其左字节点不为空,则左字节点入栈,这样出栈时,则会先出左子节点,再出右子节点,则能够完成树的前序遍历
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| vector<int> preOrderTraversal(TreeNode* root) { vector<int> res; if (root == nullptr){ return res; } stack<TreeNode*> s; s.push(root); while (!s.empty()){ TreeNode* temp = s.top(); s.pop(); res.push_back(temp->val); if (temp->right){ s.push(temp->right); } if (temp->left){ s.push(temp->left); } } return res; }
|
中序遍历
递归实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| vector<int> inOrderTraversal(TreeNode* root) { vector<int> res; inOrder(root,res); return res; }
void inOrder(TreeNode* root, vector<int> &res){ if (root == nullptr){ return; } inOrder(root->left,res); res.push_back(root->val); inOrder(root->right,res); }
|
非递归实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| vector<int> inorderTraversal(TreeNode* root) { vector<int> res; if (root == nullptr){ return res; } stack<TreeNode*> stk; while (!stk.empty() || root != nullptr){ while (root != nullptr){ stk.push(root); root = root->left; } root = stk.top(); stk.pop(); res.push_back(root->val); root = root->right; } return res; }
|
后序遍历
递归实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| vector<int> postOrderTraversal(TreeNode* root) { vector<int> res; postOrder(root,res); return res; }
void postOrder(TreeNode* root, vector<int> &res){ if (root == nullptr){ return; } postOrder(root->left,res); postOrder(root->right,res); res.push_back(root->val); }
|
非递归实现
因为后序遍历二叉树的顺序是先访问左子树,再访问右子树,最后访问根节点。当用堆栈来存储节点,必须分清返回根节点时,是从左子树返回的,还从右子树返回的。所以,使用辅助指针prev指向最近访问过的节点,来判断是否从右子树返回。也可以在节点中增加一个标志域,记录是否已被访问。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| vector<int> postorderTraversal(TreeNode* root) { vector<int> res; if (root == nullptr){ return res; } stack<TreeNode*> stk; TreeNode* prev = nullptr; while (root != nullptr || !stk.empty()){ while (root != nullptr){ stk.push(root); root = root->left; } root = stk.top(); stk.pop(); if (root->right && root->right != prev){ stk.push(root); root = root->right; }else{ res.push_back(root->val); prev = root; root = nullptr; } } return res; }
|
按层次遍历
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| vector<vector<int>> levelOrder(TreeNode* root) { vector<vector<int>> result; if (root == nullptr){ return result; } queue<TreeNode*> q; q.push(root); while (!q.empty()){ vector<int> temp; int n = q.size(); for (int i = 0; i < n; i++){ TreeNode* node = q.front(); q.pop(); temp.push_back(node->val); if (node->left != nullptr){ q.push(node->left); } if (node->right != nullptr){ q.push(node->right); } } result.push_back(temp); } return result; }
|