二叉樹的前序、中序、後序、層次遍歷的遞迴與非遞迴實現
阿新 • • 發佈:2019-02-02
二叉樹的遍歷有前序遍歷、中序遍歷、後序遍歷、層次遍歷等,筆者在這裡總結一下各種遍歷的實現。
一.前序遍歷。
前序遍歷訪問節點順序為:根節點->左子節點->右子節點。
遞迴實現如下:
void preorder(TreeNode* root, vector<int>& nodes) { if (!root) return; nodes.push_back(root -> val); preorder(root -> left, nodes); preorder(root -> right, nodes); } vector<int> preorderTraversal(TreeNode* root) { vector<int> nodes; preorder(root, nodes); return nodes; }
非遞迴實現(使用棧)如下:
對於任一結點P:
①訪問結點P,並將結點P入棧;
②判斷結點P的左孩子是否為空,若為空,則取棧頂結點並進行出棧操作,並將棧頂結點的右孩子置為當前的結點P,迴圈至①;若不為空,則將P的左孩子置為當前的結點P;
③直到P為NULL並且棧為空,則遍歷結束。
vector<int> preorderTraversal(TreeNode *root) { vector<int> v; if (root == NULL) return v; stack<TreeNode*> s; TreeNode* temp = root; while (temp != NULL || !s.empty()) { while (temp != NULL) { v.push_back(temp->val); s.push(temp); temp = temp->left; } if (!s.empty()) { temp = s.top(); s.pop(); temp = temp->right; } } return v; }
二.中序遍歷。
中序遍歷訪問節點順序為:左子節點->根節點->右子節點。
遞迴實現如下:
void inorder(TreeNode* root, vector<int>& nodes) { if (!root) return; inorder(root -> left, nodes); nodes.push_back(root -> val); inorder(root -> right, nodes); } vector<int> inorderTraversal(TreeNode* root) { vector<int> nodes; inorder(root, nodes); return nodes; }
非遞迴實現(使用棧)如下:
對於任一結點P,
①若其左孩子不為空,則將P入棧並將P的左孩子置為當前的P,然後對當前結點P再進行相同的處理;
②若其左孩子為空,則取棧頂元素並進行出棧操作,訪問該棧頂結點,然後將當前的P置為棧頂結點的右孩子;
③直到P為NULL並且棧為空則遍歷結束
vector<int> inorderTraversal(TreeNode *root) {
vector<int> v;
if (root == NULL) return v;
stack<TreeNode*> s;
TreeNode *temp = root;
while (temp != NULL || !s.empty()) {
while (temp != NULL) {
s.push(temp);
temp = temp->left;
}
if (!s.empty()) {
temp = s.top();
s.pop();
v.push_back(temp->val);
temp = temp->right;
}
}
return v;
}
三.後序遍歷。
後序遍歷訪問節點順序為:左子節點->右子節點->根節點。
遞迴實現如下:
void postorder(TreeNode* root, vector<int>& nodes) {
if (!root) return;
postorder(root -> left, nodes);
postorder(root -> right, nodes);
nodes.push_back(root -> val);
}
vector<int> postorderTraversal(TreeNode* root) {
vector<int> nodes;
postorder(root, nodes);
return nodes;
}
非遞迴實現(使用棧)如下:
vector<int> postorderTraversal(TreeNode *root) {
vector<int> v;
stack<TreeNode*> s;
TreeNode * curr = root;
TreeNode * previsited = NULL;
while (curr != NULL || !s.empty()) {
while (curr != NULL) {
s.push(curr);
curr = curr->left;
}
curr = s.top();
// 當前節點的右孩子如果為空或者已經被訪問,則訪問當前節點
if (curr->right == NULL || curr->right == previsited) {
v.push_back(curr->val);
previsited = curr;
s.pop();
curr = NULL;
}
else curr = curr->right; //否則訪問右孩子
}
return v;
}
四.層次遍歷。
使用佇列:
vector<vector<int>> levelOrder(TreeNode *root) {
queue<TreeNode*> q;
int count = 0;
vector<int> v;
vector<vector<int>> v2;
if (root == NULL) return v2;
q.push(root);
count++;
int count2 = 1;
while (!q.empty()) {
count = count2;
count2 = 0;
v.clear();
for (int i = 0; i < count; i++) {
TreeNode * top = q.front();
v.push_back(top->val);
if (top->left != NULL) {
q.push(top->left);
count2++;
}
if (top->right != NULL) {
q.push(top->right);
count2++;
}
q.pop();
}
v2.push_back(v);
}
return v2;
}