1.前序遍歷
前序遍歷:先遍歷根節點,再遍歷左子樹,最后遍歷右子樹(根-左-右)
測試代碼:

// 二叉樹的三種遍歷 // 1.前序遍歷 // 2.中序遍歷 // 3.后序遍歷 #include <cstdio> #include <stack> #include <vector> #include "BinaryTree.h" using namespace std; void visitAlongLeftBranch(BinaryTreeNode* , vector<int>& , stack<BinaryTreeNode*>&); void TraverseBinaryTree(BinaryTreeNode* pRoot, vector<int>& treeNodes) //二叉樹前序遍歷算法(迭代版) { stack<BinaryTreeNode*> S; //輔助棧 while (true) { visitAlongLeftBranch(pRoot, treeNodes, S); //從當前節點逐批訪問 if (S.empty()) break; //棧為空, 彈出 pRoot = S.top(); //彈出下一批的起點 S.pop(); } } //從當前節點出發, 沿左分支不斷深入, 直至沒有左分支的節點; 沿途節點遇到后立即訪問 void visitAlongLeftBranch(BinaryTreeNode* pRoot, vector<int>& treeNodes, stack<BinaryTreeNode*>& S) { while (pRoot) { treeNodes.push_back(pRoot->m_nValue); //訪問當前節點 S.push(pRoot->m_pRight); //右子節點入棧暫存 pRoot = pRoot->m_pLeft; //沿左分支深入一層 } } // ====================測試代碼==================== void Test(const char* testName, BinaryTreeNode* pRoot, vector<int> expectedPre, vector<int> expectedIn, vector<int> expectedPost, int expectedLength) { if (testName != nullptr) printf("%s begins: ", testName); vector<int> treeNodes; //保存遍歷值 TraverseBinaryTree(pRoot, treeNodes); int length = treeNodes.size(); bool flag = true; //標志位 if (length != expectedLength) flag = false; //長度不一致, 則遍歷算法錯誤 for (int i = 0; i < length; ++i) //順序不一致, 則遍歷算法錯誤 { if (treeNodes[i] != expectedPre[i]) //注意:遍歷期望值在這里改 flag = false; } if (flag) printf("Passed."); else printf("Failed."); //打印遍歷值 printf("\nExpected: "); for (int i = 0; i < expectedLength; ++i) printf("%d ", expectedPre[i]); //注意:遍歷期望值在這里改 printf("\nActual: "); for (int i = 0; i < length; ++i) printf("%d ", treeNodes[i]); printf("\n\n"); } // 1.滿二叉樹 // 10 // / \ // 6 14 // /\ /\ // 4 8 12 16 void Test1() { BinaryTreeNode* pNode10 = CreateBinaryTreeNode(10); BinaryTreeNode* pNode6 = CreateBinaryTreeNode(6); BinaryTreeNode* pNode14 = CreateBinaryTreeNode(14); BinaryTreeNode* pNode4 = CreateBinaryTreeNode(4); BinaryTreeNode* pNode8 = CreateBinaryTreeNode(8); BinaryTreeNode* pNode12 = CreateBinaryTreeNode(12); BinaryTreeNode* pNode16 = CreateBinaryTreeNode(16); ConnectTreeNodes(pNode10, pNode6, pNode14); ConnectTreeNodes(pNode6, pNode4, pNode8); ConnectTreeNodes(pNode14, pNode12, pNode16); vector<int> expectedPre = {10, 6, 4, 8, 14, 12, 16}; vector<int> expectedIn = {4, 6, 8, 10, 12, 14, 16}; vector<int> expectedPost = {4, 8, 6, 12, 16, 14, 10}; Test("Test1", pNode10, expectedPre, expectedIn, expectedPost, 7); DestroyTree(pNode10); } // 2.完全二叉樹 // 10 // / \ // 6 14 // /\ / // 4 8 12 void Test2() { BinaryTreeNode* pNode10 = CreateBinaryTreeNode(10); BinaryTreeNode* pNode6 = CreateBinaryTreeNode(6); BinaryTreeNode* pNode14 = CreateBinaryTreeNode(14); BinaryTreeNode* pNode4 = CreateBinaryTreeNode(4); BinaryTreeNode* pNode8 = CreateBinaryTreeNode(8); BinaryTreeNode* pNode12 = CreateBinaryTreeNode(12); ConnectTreeNodes(pNode10, pNode6, pNode14); ConnectTreeNodes(pNode6, pNode4, pNode8); ConnectTreeNodes(pNode14, pNode12, nullptr); vector<int> expectedPre = { 10, 6, 4, 8, 14, 12}; vector<int> expectedIn = { 4, 6, 8, 10, 12, 14}; vector<int> expectedPost = { 4, 8, 6, 12, 14, 10 }; Test("Test2", pNode10, expectedPre, expectedIn, expectedPost, 6); DestroyTree(pNode10); } // 3.二叉樹 // 10 // / \ // 6 14 // \ / // 8 12 // / // 4 void Test3() { BinaryTreeNode* pNode10 = CreateBinaryTreeNode(10); BinaryTreeNode* pNode6 = CreateBinaryTreeNode(6); BinaryTreeNode* pNode14 = CreateBinaryTreeNode(14); BinaryTreeNode* pNode8 = CreateBinaryTreeNode(8); BinaryTreeNode* pNode4 = CreateBinaryTreeNode(4); BinaryTreeNode* pNode12 = CreateBinaryTreeNode(12); ConnectTreeNodes(pNode10, pNode6, pNode14); ConnectTreeNodes(pNode6, nullptr , pNode8); ConnectTreeNodes(pNode8, pNode4, nullptr); ConnectTreeNodes(pNode14, pNode12, nullptr); vector<int> expectedPre = { 10, 6, 8, 4, 14, 12 }; vector<int> expectedIn = { 6, 4, 8, 10, 12, 14 }; vector<int> expectedPost = { 4, 8, 6, 12, 14, 10 }; Test("Test3", pNode10, expectedPre, expectedIn, expectedPost, 6); DestroyTree(pNode10); } // 4.只有最左側通路 // 5 // / // 4 // / // 3 // / // 2 // / // 1 void Test4() { BinaryTreeNode* pNode5 = CreateBinaryTreeNode(5); BinaryTreeNode* pNode4 = CreateBinaryTreeNode(4); BinaryTreeNode* pNode3 = CreateBinaryTreeNode(3); BinaryTreeNode* pNode2 = CreateBinaryTreeNode(2); BinaryTreeNode* pNode1 = CreateBinaryTreeNode(1); ConnectTreeNodes(pNode5, pNode4, nullptr); ConnectTreeNodes(pNode4, pNode3, nullptr); ConnectTreeNodes(pNode3, pNode2, nullptr); ConnectTreeNodes(pNode2, pNode1, nullptr); vector<int> expectedPre = {5, 4, 3, 2, 1}; vector<int> expectedIn = {1, 2, 3, 4, 5}; vector<int> expectedPost = {1, 2, 3, 4, 5}; Test("Test4", pNode5, expectedPre, expectedIn, expectedPost, 5); DestroyTree(pNode5); } // 4.只有最右側通路 // 1 // \ // 2 // \ // 3 // \ // 4 // \ // 5 void Test5() { BinaryTreeNode* pNode1 = CreateBinaryTreeNode(1); BinaryTreeNode* pNode2 = CreateBinaryTreeNode(2); BinaryTreeNode* pNode3 = CreateBinaryTreeNode(3); BinaryTreeNode* pNode4 = CreateBinaryTreeNode(4); BinaryTreeNode* pNode5 = CreateBinaryTreeNode(5); ConnectTreeNodes(pNode1, nullptr, pNode2); ConnectTreeNodes(pNode2, nullptr, pNode3); ConnectTreeNodes(pNode3, nullptr, pNode4); ConnectTreeNodes(pNode4, nullptr, pNode5); vector<int> expectedPre = {1, 2, 3, 4, 5}; vector<int> expectedIn = { 1, 2, 3, 4, 5 }; vector<int> expectedPost = {5, 4, 3, 2, 1}; Test("Test5", pNode1, expectedPre, expectedIn, expectedPost, 5); DestroyTree(pNode1); } // 樹中只有1個結點 void Test6() { BinaryTreeNode* pNode1 = CreateBinaryTreeNode(1); vector<int> expectedPre = {1}; vector<int> expectedIn = {1}; vector<int> expectedPost = {1}; Test("Test6", pNode1, expectedPre, expectedIn, expectedPost, 1); DestroyTree(pNode1); } // 樹中沒有結點 void Test7() { vector<int> expectedPre = {}; vector<int> expectedIn = {}; vector<int> expectedPost = {}; Test("Test7", nullptr, expectedPre, expectedIn, expectedPost, 0); } int main(int argc, char* argv[]) { Test1(); Test2(); Test3(); Test4(); Test5(); Test6(); Test7(); return 0; }
1.1 基於遞歸實現
void TraverseBinaryTree(BinaryTreeNode* pRoot, vector<int>& treeNodes) //二叉樹前序遍歷算法(遞歸版) { if (pRoot == nullptr) return; treeNodes.push_back(pRoot->m_nValue); TraverseBinaryTree(pRoot->m_pLeft, treeNodes); TraverseBinaryTree(pRoot->m_pRight, treeNodes); }
1.2 基於迭代實現
由於沒有指向父節點的指針,所以需要輔助棧來記錄路徑中的右子節點。
void visitAlongLeftBranch(BinaryTreeNode* , vector<int>& , stack<BinaryTreeNode*>&); void TraverseBinaryTree(BinaryTreeNode* pRoot, vector<int>& treeNodes) //二叉樹前序遍歷算法(迭代版) { stack<BinaryTreeNode*> S; //輔助棧 while (true) { visitAlongLeftBranch(pRoot, treeNodes, S); //從當前節點逐批訪問 if (S.empty()) break; //棧為空, 彈出 pRoot = S.top(); //彈出下一批的起點 S.pop(); } } //從當前節點出發, 沿左分支不斷深入, 直至沒有左分支的節點; 沿途節點遇到后立即訪問 void visitAlongLeftBranch(BinaryTreeNode* pRoot, vector<int>& treeNodes, stack<BinaryTreeNode*>& S) { while (pRoot) { treeNodes.push_back(pRoot->m_nValue); //訪問當前節點 S.push(pRoot->m_pRight); //右子節點入棧暫存 pRoot = pRoot->m_pLeft; //沿左分支深入一層 } }
LeetCode
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: vector<int> preorderTraversal(TreeNode* root) { vector<int> ret; //保存路徑值 stack<TreeNode*> S; //輔助棧 while (true) { if (root) //尋找最左節點 { ret.push_back(root->val); //中途節點直接訪問 S.push(root->right); //暫存右子節點 root = root->left; } else if (!S.empty()) { root = S.top(); S.pop(); } else break; } return ret; } };
2.中序遍歷
中序遍歷:先遍歷左子樹,再遍歷根節點,最后遍歷右子樹(左-根-右)
測試代碼:

// 二叉樹的三種遍歷 // 1.前序遍歷 // 2.中序遍歷 // 3.后序遍歷 #include <cstdio> #include <stack> #include <vector> #include "BinaryTree.h" using namespace std; void goAlongLeftBranch(BinaryTreeNode*, stack<BinaryTreeNode*>&); void TraverseBinaryTree(BinaryTreeNode* pRoot, vector<int>& treeNodes) //二叉樹中序遍歷算法(迭代版#1) { stack<BinaryTreeNode*> S; //輔助棧 while (true) { goAlongLeftBranch(pRoot, S); //從當前節點出發,逐批入棧 if (S.empty()) break; //直至所有節點處理完畢 pRoot = S.top(); //彈出棧頂節點並訪問 S.pop(); treeNodes.push_back(pRoot->m_nValue); pRoot = pRoot->m_pRight; //轉向右子樹 } } //從當前節點出發, 沿左分支不斷深入, 直至沒有左分支的節點 void goAlongLeftBranch(BinaryTreeNode* pRoot, stack<BinaryTreeNode*>& S) { while (pRoot) //當前節點入棧后隨機向左側分支深入, 迭代到無左子節點 { S.push(pRoot); pRoot = pRoot->m_pLeft; } } // ====================測試代碼==================== void Test(const char* testName, BinaryTreeNode* pRoot, vector<int> expectedPre, vector<int> expectedIn, vector<int> expectedPost, int expectedLength) { if (testName != nullptr) printf("%s begins: ", testName); vector<int> treeNodes; //保存遍歷值 TraverseBinaryTree(pRoot, treeNodes); int length = treeNodes.size(); bool flag = true; //標志位 if (length != expectedLength) flag = false; //長度不一致, 則遍歷算法錯誤 for (int i = 0; i < length; ++i) //順序不一致, 則遍歷算法錯誤 { if (treeNodes[i] != expectedIn[i]) //注意:遍歷期望值在這里改 flag = false; } if (flag) printf("Passed."); else printf("Failed."); //打印遍歷值 printf("\nExpected: "); for (int i = 0; i < expectedLength; ++i) printf("%d ", expectedIn[i]); //注意:遍歷期望值在這里改 printf("\nActual: "); for (int i = 0; i < length; ++i) printf("%d ", treeNodes[i]); printf("\n\n"); } // 1.滿二叉樹 // 10 // / \ // 6 14 // /\ /\ // 4 8 12 16 void Test1() { BinaryTreeNode* pNode10 = CreateBinaryTreeNode(10); BinaryTreeNode* pNode6 = CreateBinaryTreeNode(6); BinaryTreeNode* pNode14 = CreateBinaryTreeNode(14); BinaryTreeNode* pNode4 = CreateBinaryTreeNode(4); BinaryTreeNode* pNode8 = CreateBinaryTreeNode(8); BinaryTreeNode* pNode12 = CreateBinaryTreeNode(12); BinaryTreeNode* pNode16 = CreateBinaryTreeNode(16); ConnectTreeNodes(pNode10, pNode6, pNode14); ConnectTreeNodes(pNode6, pNode4, pNode8); ConnectTreeNodes(pNode14, pNode12, pNode16); vector<int> expectedPre = {10, 6, 4, 8, 14, 12, 16}; vector<int> expectedIn = {4, 6, 8, 10, 12, 14, 16}; vector<int> expectedPost = {4, 8, 6, 12, 16, 14, 10}; Test("Test1", pNode10, expectedPre, expectedIn, expectedPost, 7); DestroyTree(pNode10); } // 2.完全二叉樹 // 10 // / \ // 6 14 // /\ / // 4 8 12 void Test2() { BinaryTreeNode* pNode10 = CreateBinaryTreeNode(10); BinaryTreeNode* pNode6 = CreateBinaryTreeNode(6); BinaryTreeNode* pNode14 = CreateBinaryTreeNode(14); BinaryTreeNode* pNode4 = CreateBinaryTreeNode(4); BinaryTreeNode* pNode8 = CreateBinaryTreeNode(8); BinaryTreeNode* pNode12 = CreateBinaryTreeNode(12); ConnectTreeNodes(pNode10, pNode6, pNode14); ConnectTreeNodes(pNode6, pNode4, pNode8); ConnectTreeNodes(pNode14, pNode12, nullptr); vector<int> expectedPre = { 10, 6, 4, 8, 14, 12}; vector<int> expectedIn = { 4, 6, 8, 10, 12, 14}; vector<int> expectedPost = { 4, 8, 6, 12, 14, 10 }; Test("Test2", pNode10, expectedPre, expectedIn, expectedPost, 6); DestroyTree(pNode10); } // 3.二叉樹 // 10 // / \ // 6 14 // \ / // 8 12 // / // 4 void Test3() { BinaryTreeNode* pNode10 = CreateBinaryTreeNode(10); BinaryTreeNode* pNode6 = CreateBinaryTreeNode(6); BinaryTreeNode* pNode14 = CreateBinaryTreeNode(14); BinaryTreeNode* pNode8 = CreateBinaryTreeNode(8); BinaryTreeNode* pNode4 = CreateBinaryTreeNode(4); BinaryTreeNode* pNode12 = CreateBinaryTreeNode(12); ConnectTreeNodes(pNode10, pNode6, pNode14); ConnectTreeNodes(pNode6, nullptr , pNode8); ConnectTreeNodes(pNode8, pNode4, nullptr); ConnectTreeNodes(pNode14, pNode12, nullptr); vector<int> expectedPre = { 10, 6, 8, 4, 14, 12 }; vector<int> expectedIn = { 6, 4, 8, 10, 12, 14 }; vector<int> expectedPost = { 4, 8, 6, 12, 14, 10 }; Test("Test3", pNode10, expectedPre, expectedIn, expectedPost, 6); DestroyTree(pNode10); } // 4.只有最左側通路 // 5 // / // 4 // / // 3 // / // 2 // / // 1 void Test4() { BinaryTreeNode* pNode5 = CreateBinaryTreeNode(5); BinaryTreeNode* pNode4 = CreateBinaryTreeNode(4); BinaryTreeNode* pNode3 = CreateBinaryTreeNode(3); BinaryTreeNode* pNode2 = CreateBinaryTreeNode(2); BinaryTreeNode* pNode1 = CreateBinaryTreeNode(1); ConnectTreeNodes(pNode5, pNode4, nullptr); ConnectTreeNodes(pNode4, pNode3, nullptr); ConnectTreeNodes(pNode3, pNode2, nullptr); ConnectTreeNodes(pNode2, pNode1, nullptr); vector<int> expectedPre = {5, 4, 3, 2, 1}; vector<int> expectedIn = {1, 2, 3, 4, 5}; vector<int> expectedPost = {1, 2, 3, 4, 5}; Test("Test4", pNode5, expectedPre, expectedIn, expectedPost, 5); DestroyTree(pNode5); } // 4.只有最右側通路 // 1 // \ // 2 // \ // 3 // \ // 4 // \ // 5 void Test5() { BinaryTreeNode* pNode1 = CreateBinaryTreeNode(1); BinaryTreeNode* pNode2 = CreateBinaryTreeNode(2); BinaryTreeNode* pNode3 = CreateBinaryTreeNode(3); BinaryTreeNode* pNode4 = CreateBinaryTreeNode(4); BinaryTreeNode* pNode5 = CreateBinaryTreeNode(5); ConnectTreeNodes(pNode1, nullptr, pNode2); ConnectTreeNodes(pNode2, nullptr, pNode3); ConnectTreeNodes(pNode3, nullptr, pNode4); ConnectTreeNodes(pNode4, nullptr, pNode5); vector<int> expectedPre = {1, 2, 3, 4, 5}; vector<int> expectedIn = { 1, 2, 3, 4, 5 }; vector<int> expectedPost = {5, 4, 3, 2, 1}; Test("Test5", pNode1, expectedPre, expectedIn, expectedPost, 5); DestroyTree(pNode1); } // 樹中只有1個結點 void Test6() { BinaryTreeNode* pNode1 = CreateBinaryTreeNode(1); vector<int> expectedPre = {1}; vector<int> expectedIn = {1}; vector<int> expectedPost = {1}; Test("Test6", pNode1, expectedPre, expectedIn, expectedPost, 1); DestroyTree(pNode1); } // 樹中沒有結點 void Test7() { vector<int> expectedPre = {}; vector<int> expectedIn = {}; vector<int> expectedPost = {}; Test("Test7", nullptr, expectedPre, expectedIn, expectedPost, 0); } int main(int argc, char* argv[]) { Test1(); Test2(); Test3(); Test4(); Test5(); Test6(); Test7(); return 0; }
2.1 基於遞歸實現
void TraverseBinaryTree(BinaryTreeNode* pRoot, vector<int>& treeNodes) //二叉樹中序遍歷算法(遞歸版) { if (pRoot == nullptr) return; TraverseBinaryTree(pRoot->m_pLeft, treeNodes); treeNodes.push_back(pRoot->m_nValue); TraverseBinaryTree(pRoot->m_pRight, treeNodes); }
2.2 基於迭代實現
void goAlongLeftBranch(BinaryTreeNode*, stack<BinaryTreeNode*>&); void TraverseBinaryTree(BinaryTreeNode* pRoot, vector<int>& treeNodes) //二叉樹中序遍歷算法(迭代版#1) { stack<BinaryTreeNode*> S; //輔助棧 while (true) { goAlongLeftBranch(pRoot, S); //從當前節點出發,逐批入棧 if (S.empty()) break; //直至所有節點處理完畢 pRoot = S.top(); //彈出棧頂節點並訪問 S.pop(); treeNodes.push_back(pRoot->m_nValue); pRoot = pRoot->m_pRight; //轉向右子樹 } } //從當前節點出發, 沿左分支不斷深入, 直至沒有左分支的節點 void goAlongLeftBranch(BinaryTreeNode* pRoot, stack<BinaryTreeNode*>& S) { while (pRoot) //當前節點入棧后隨即向左側分支深入, 迭代到無左子節點 { S.push(pRoot); pRoot = pRoot->m_pLeft; } }
void TraverseBinaryTree(BinaryTreeNode* pRoot, vector<int>& treeNodes) //二叉樹中序遍歷算法(迭代版#2) { stack<BinaryTreeNode*> S; //輔助棧 while (true) { if (pRoot) { S.push(pRoot); //根節點進棧 pRoot = pRoot->m_pLeft; //深入遍歷左子樹 } else if (!S.empty()) { pRoot = S.top(); //尚未訪問的最低祖先節點退棧 S.pop(); treeNodes.push_back(pRoot->m_nValue); pRoot = pRoot->m_pRight; //轉向右子樹 } else break; } }
3. 后序遍歷
后序遍歷:先遍歷左子樹,再遍歷右子樹,最后遍歷根節點(左-右-根)
測試代碼:

// 二叉樹的三種遍歷 // 1.前序遍歷 // 2.中序遍歷 // 3.后序遍歷 #include <cstdio> #include <stack> #include <vector> #include "BinaryTree.h" using namespace std; void gotoHLVFL(stack<BinaryTreeNode*>&); void TraverseBinaryTree(BinaryTreeNode* pRoot, vector<int>& treeNodes) //二叉樹后序遍歷算法(迭代版) { stack<BinaryTreeNode*> S; //輔助棧 if (pRoot) S.push(pRoot); //根節點進棧 while (!S.empty()) { if ((S.top()->m_pLeft != pRoot) // 若棧頂非當前節點的父節點(必為其右兄) && (S.top()->m_pRight != pRoot)) // 在以其右兄為根的子樹中, 找到HLVFL gotoHLVFL(S); pRoot = S.top(); S.pop(); if (pRoot) treeNodes.push_back(pRoot->m_nValue); } } // 在以S棧頂節點為根的子樹中, 找到最高左側可見節點 void gotoHLVFL(stack<BinaryTreeNode*>& S) { while (BinaryTreeNode* pRoot = S.top()) // 自頂向下, 反復檢查當前節點(即棧頂) { if (pRoot->m_pLeft) // 盡可能向左 { if (pRoot->m_pRight) //若有右子節點, 優先入棧 S.push(pRoot->m_pRight); S.push(pRoot->m_pLeft); //然后轉入左子節點 } else //只有右子節點 S.push(pRoot->m_pRight); } S.pop(); } // ====================測試代碼==================== void Test(const char* testName, BinaryTreeNode* pRoot, vector<int> expectedPre, vector<int> expectedIn, vector<int> expectedPost, int expectedLength) { if (testName != nullptr) printf("%s begins: ", testName); vector<int> treeNodes; //保存遍歷值 TraverseBinaryTree(pRoot, treeNodes); int length = treeNodes.size(); bool flag = true; //標志位 if (length != expectedLength) flag = false; //長度不一致, 則遍歷算法錯誤 for (int i = 0; i < length; ++i) //順序不一致, 則遍歷算法錯誤 { if (treeNodes[i] != expectedPost[i]) //注意:遍歷期望值在這里改 flag = false; } if (flag) printf("Passed."); else printf("Failed."); //打印遍歷值 printf("\nExpected: "); for (int i = 0; i < expectedLength; ++i) printf("%d ", expectedPost[i]); //注意:遍歷期望值在這里改 printf("\nActual: "); for (int i = 0; i < length; ++i) printf("%d ", treeNodes[i]); printf("\n\n"); } // 1.滿二叉樹 // 10 // / \ // 6 14 // /\ /\ // 4 8 12 16 void Test1() { BinaryTreeNode* pNode10 = CreateBinaryTreeNode(10); BinaryTreeNode* pNode6 = CreateBinaryTreeNode(6); BinaryTreeNode* pNode14 = CreateBinaryTreeNode(14); BinaryTreeNode* pNode4 = CreateBinaryTreeNode(4); BinaryTreeNode* pNode8 = CreateBinaryTreeNode(8); BinaryTreeNode* pNode12 = CreateBinaryTreeNode(12); BinaryTreeNode* pNode16 = CreateBinaryTreeNode(16); ConnectTreeNodes(pNode10, pNode6, pNode14); ConnectTreeNodes(pNode6, pNode4, pNode8); ConnectTreeNodes(pNode14, pNode12, pNode16); vector<int> expectedPre = {10, 6, 4, 8, 14, 12, 16}; vector<int> expectedIn = {4, 6, 8, 10, 12, 14, 16}; vector<int> expectedPost = {4, 8, 6, 12, 16, 14, 10}; Test("Test1", pNode10, expectedPre, expectedIn, expectedPost, 7); DestroyTree(pNode10); } // 2.完全二叉樹 // 10 // / \ // 6 14 // /\ / // 4 8 12 void Test2() { BinaryTreeNode* pNode10 = CreateBinaryTreeNode(10); BinaryTreeNode* pNode6 = CreateBinaryTreeNode(6); BinaryTreeNode* pNode14 = CreateBinaryTreeNode(14); BinaryTreeNode* pNode4 = CreateBinaryTreeNode(4); BinaryTreeNode* pNode8 = CreateBinaryTreeNode(8); BinaryTreeNode* pNode12 = CreateBinaryTreeNode(12); ConnectTreeNodes(pNode10, pNode6, pNode14); ConnectTreeNodes(pNode6, pNode4, pNode8); ConnectTreeNodes(pNode14, pNode12, nullptr); vector<int> expectedPre = { 10, 6, 4, 8, 14, 12}; vector<int> expectedIn = { 4, 6, 8, 10, 12, 14}; vector<int> expectedPost = { 4, 8, 6, 12, 14, 10 }; Test("Test2", pNode10, expectedPre, expectedIn, expectedPost, 6); DestroyTree(pNode10); } // 3.二叉樹 // 10 // / \ // 6 14 // \ / // 8 12 // / // 4 void Test3() { BinaryTreeNode* pNode10 = CreateBinaryTreeNode(10); BinaryTreeNode* pNode6 = CreateBinaryTreeNode(6); BinaryTreeNode* pNode14 = CreateBinaryTreeNode(14); BinaryTreeNode* pNode8 = CreateBinaryTreeNode(8); BinaryTreeNode* pNode4 = CreateBinaryTreeNode(4); BinaryTreeNode* pNode12 = CreateBinaryTreeNode(12); ConnectTreeNodes(pNode10, pNode6, pNode14); ConnectTreeNodes(pNode6, nullptr , pNode8); ConnectTreeNodes(pNode8, pNode4, nullptr); ConnectTreeNodes(pNode14, pNode12, nullptr); vector<int> expectedPre = { 10, 6, 8, 4, 14, 12 }; vector<int> expectedIn = { 6, 4, 8, 10, 12, 14 }; vector<int> expectedPost = { 4, 8, 6, 12, 14, 10 }; Test("Test3", pNode10, expectedPre, expectedIn, expectedPost, 6); DestroyTree(pNode10); } // 4.只有最左側通路 // 5 // / // 4 // / // 3 // / // 2 // / // 1 void Test4() { BinaryTreeNode* pNode5 = CreateBinaryTreeNode(5); BinaryTreeNode* pNode4 = CreateBinaryTreeNode(4); BinaryTreeNode* pNode3 = CreateBinaryTreeNode(3); BinaryTreeNode* pNode2 = CreateBinaryTreeNode(2); BinaryTreeNode* pNode1 = CreateBinaryTreeNode(1); ConnectTreeNodes(pNode5, pNode4, nullptr); ConnectTreeNodes(pNode4, pNode3, nullptr); ConnectTreeNodes(pNode3, pNode2, nullptr); ConnectTreeNodes(pNode2, pNode1, nullptr); vector<int> expectedPre = {5, 4, 3, 2, 1}; vector<int> expectedIn = {1, 2, 3, 4, 5}; vector<int> expectedPost = {1, 2, 3, 4, 5}; Test("Test4", pNode5, expectedPre, expectedIn, expectedPost, 5); DestroyTree(pNode5); } // 4.只有最右側通路 // 1 // \ // 2 // \ // 3 // \ // 4 // \ // 5 void Test5() { BinaryTreeNode* pNode1 = CreateBinaryTreeNode(1); BinaryTreeNode* pNode2 = CreateBinaryTreeNode(2); BinaryTreeNode* pNode3 = CreateBinaryTreeNode(3); BinaryTreeNode* pNode4 = CreateBinaryTreeNode(4); BinaryTreeNode* pNode5 = CreateBinaryTreeNode(5); ConnectTreeNodes(pNode1, nullptr, pNode2); ConnectTreeNodes(pNode2, nullptr, pNode3); ConnectTreeNodes(pNode3, nullptr, pNode4); ConnectTreeNodes(pNode4, nullptr, pNode5); vector<int> expectedPre = {1, 2, 3, 4, 5}; vector<int> expectedIn = { 1, 2, 3, 4, 5 }; vector<int> expectedPost = {5, 4, 3, 2, 1}; Test("Test5", pNode1, expectedPre, expectedIn, expectedPost, 5); DestroyTree(pNode1); } // 樹中只有1個結點 void Test6() { BinaryTreeNode* pNode1 = CreateBinaryTreeNode(1); vector<int> expectedPre = {1}; vector<int> expectedIn = {1}; vector<int> expectedPost = {1}; Test("Test6", pNode1, expectedPre, expectedIn, expectedPost, 1); DestroyTree(pNode1); } // 樹中沒有結點 void Test7() { vector<int> expectedPre = {}; vector<int> expectedIn = {}; vector<int> expectedPost = {}; Test("Test7", nullptr, expectedPre, expectedIn, expectedPost, 0); } int main(int argc, char* argv[]) { Test1(); Test2(); Test3(); Test4(); Test5(); Test6(); Test7(); return 0; }
3.1 基於遞歸實現
void TraverseBinaryTree(BinaryTreeNode* pRoot, vector<int>& treeNodes) //二叉樹后序遍歷算法(遞歸版) { if (pRoot == nullptr) return; //后序遍歷 TraverseBinaryTree(pRoot->m_pLeft, treeNodes); TraverseBinaryTree(pRoot->m_pRight, treeNodes); treeNodes.push_back(pRoot->m_nValue); }
3.2 基於迭代實現
void gotoHLVFL(stack<BinaryTreeNode*>&); void TraverseBinaryTree(BinaryTreeNode* pRoot, vector<int>& treeNodes) //二叉樹后序遍歷算法(迭代版) { stack<BinaryTreeNode*> S; //輔助棧 if (pRoot) S.push(pRoot); //根節點進棧 while (!S.empty()) { if ((S.top()->m_pLeft != pRoot) // 若棧頂非當前節點的父節點(必為其右兄) && (S.top()->m_pRight != pRoot)) // 在以其右兄為根的子樹中, 找到HLVFL gotoHLVFL(S); pRoot = S.top(); S.pop(); if (pRoot) treeNodes.push_back(pRoot->m_nValue); } } // 在以S棧頂節點為根的子樹中, 找到最高左側可見節點 void gotoHLVFL(stack<BinaryTreeNode*>& S) { while (BinaryTreeNode* pRoot = S.top()) // 自頂向下, 反復檢查當前節點(即棧頂) { if (pRoot->m_pLeft) // 盡可能向左 { if (pRoot->m_pRight) //若有右子節點, 優先入棧 S.push(pRoot->m_pRight); S.push(pRoot->m_pLeft); //然后轉入左子節點 } else //只有右子節點 S.push(pRoot->m_pRight); } S.pop(); }
4. 層次遍歷
void TraverseBinaryTree(BinaryTreeNode* pRoot, vector<int>& treeNodes) //二叉樹層次遍歷算法(迭代版) { queue<BinaryTreeNode*> Q; //輔助棧 Q.push(pRoot); //根節點進棧 while (!Q.empty()) //隊列變空之前反復迭代 { BinaryTreeNode* pRoot = Q.front(); //取出首節點並訪問 treeNodes.push_back(pRoot->m_nValue); if (pRoot->m_pLeft) Q.push(pRoot->m_pLeft); if (pRoot->m_pRight) Q.push(pRoot->m_pRight); } }
可以參考之字形打印二叉樹
https://www.cnblogs.com/ZSY-blog/p/12602375.html
調用代碼:

//================================================================== // 《劍指Offer——名企面試官精講典型編程題》代碼 // 作者:何海濤 //================================================================== #pragma once struct BinaryTreeNode { int m_nValue; //節點data值 BinaryTreeNode* m_pLeft; //左子節點 BinaryTreeNode* m_pRight; //右子節點 }; __declspec( dllexport ) BinaryTreeNode* CreateBinaryTreeNode(int value); __declspec( dllexport ) void ConnectTreeNodes(BinaryTreeNode* pParent, BinaryTreeNode* pLeft, BinaryTreeNode* pRight); __declspec( dllexport ) void PrintTreeNode(const BinaryTreeNode* pNode); __declspec( dllexport ) void PrintTree(const BinaryTreeNode* pRoot); __declspec( dllexport ) void DestroyTree(BinaryTreeNode* pRoot);

//================================================================== // 《劍指Offer——名企面試官精講典型編程題》代碼 // 作者:何海濤 //================================================================== #include <cstdio> #include "BinaryTree.h" //新建一個父節點 BinaryTreeNode* CreateBinaryTreeNode(int value) { BinaryTreeNode* pNode = new BinaryTreeNode(); pNode->m_nValue = value; pNode->m_pLeft = nullptr; pNode->m_pRight = nullptr; return pNode; } //父節點連接左右子節點 void ConnectTreeNodes(BinaryTreeNode* pParent, BinaryTreeNode* pLeft, BinaryTreeNode* pRight) { if(pParent != nullptr) { pParent->m_pLeft = pLeft; pParent->m_pRight = pRight; } } //打印當前父節點以及左右子節點 void PrintTreeNode(const BinaryTreeNode* pNode) { if(pNode != nullptr) { printf("value of this node is: %d\n", pNode->m_nValue); if(pNode->m_pLeft != nullptr) printf("value of its left child is: %d.\n", pNode->m_pLeft->m_nValue); else printf("left child is nullptr.\n"); if(pNode->m_pRight != nullptr) printf("value of its right child is: %d.\n", pNode->m_pRight->m_nValue); else printf("right child is nullptr.\n"); } else { printf("this node is nullptr.\n"); } printf("\n"); } //遞歸調用打印整個二叉樹 void PrintTree(const BinaryTreeNode* pRoot) { PrintTreeNode(pRoot); if(pRoot != nullptr) { if(pRoot->m_pLeft != nullptr) PrintTree(pRoot->m_pLeft); if(pRoot->m_pRight != nullptr) PrintTree(pRoot->m_pRight); } } //遞歸調用刪除整個樹 void DestroyTree(BinaryTreeNode* pRoot) { if(pRoot != nullptr) { BinaryTreeNode* pLeft = pRoot->m_pLeft; BinaryTreeNode* pRight = pRoot->m_pRight; delete pRoot; pRoot = nullptr; DestroyTree(pLeft); DestroyTree(pRight); } }
代碼與圖參考:
[1] 劍指offer(第二版), 何海濤, 2011.
[2] 數據結構(C++語言版), 鄧俊輝, 2010.