0.二叉树的创建
0.1 二叉树节点结构
下为简单二叉树,没有考虑指向父节点的指针等。
struct BinaryTreeNode { int m_nValue; //节点data值 BinaryTreeNode* m_pLeft; //左子节点 BinaryTreeNode* m_pRight; //右子节点 };
0.2 二叉树节点的创建
//新建一个父节点 BinaryTreeNode* CreateBinaryTreeNode(int value) { BinaryTreeNode* pNode = new BinaryTreeNode(); pNode->m_nValue = value; pNode->m_pLeft = nullptr; pNode->m_pRight = nullptr; return pNode; }
0.3 二叉树节点的连接
//父节点连接左右子节点 void ConnectTreeNodes(BinaryTreeNode* pParent, BinaryTreeNode* pLeft, BinaryTreeNode* pRight) { if(pParent != nullptr) { pParent->m_pLeft = pLeft; pParent->m_pRight = pRight; } }
0.4 二叉树的删除
//递归调用删除整个树 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.前序遍历
前序遍历:先遍历根节点,再遍历左子树,最后遍历右子树(根-左-右)
测试代码:
// ====================测试代码==================== 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; for (int i = 0; i < length && length == expectedLength; ++i) { if (treeNodes[i] != expectedPre[i]) //遍历预测值在这里改一下就行 flag = false; } if (flag) printf("Passed.\n"); else printf("Failed.\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); } // 5 // / // 4 // / // 3 // / // 2 // / // 1 void Test2() { 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("Test2", pNode5, expectedPre, expectedIn, expectedPost, 5); DestroyTree(pNode5); } // 1 // \ // 2 // \ // 3 // \ // 4 // \ // 5 void Test3() { 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("Test3", pNode1, expectedPre, expectedIn, expectedPost, 5); DestroyTree(pNode1); } // 树中只有1个结点 void Test4() { BinaryTreeNode* pNode1 = CreateBinaryTreeNode(1); vector<int> expectedPre = {1}; vector<int> expectedIn = {1}; vector<int> expectedPost = {1}; Test("Test4", pNode1, expectedPre, expectedIn, expectedPost, 1); DestroyTree(pNode1); } // 树中没有结点 void Test5() { vector<int> expectedPre = {}; vector<int> expectedIn = {}; vector<int> expectedPost = {}; Test("Test5", nullptr, expectedPre, expectedIn, expectedPost, 0); } int main(int argc, char* argv[]) { Test1(); Test2(); Test3(); Test4(); Test5(); 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 基于迭代实现
2.中序遍历
中序遍历:先遍历左子树,再遍历根节点,最后遍历右子树(左-根-右)
测试代码:
// ====================测试代码==================== 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; for (int i = 0; i < length && length == expectedLength; ++i) { if (treeNodes[i] != expectedIn[i]) //遍历预测值在这里改一下就行 flag = false; } if (flag) printf("Passed.\n"); else printf("Failed.\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); } // 5 // / // 4 // / // 3 // / // 2 // / // 1 void Test2() { 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("Test2", pNode5, expectedPre, expectedIn, expectedPost, 5); DestroyTree(pNode5); } // 1 // \ // 2 // \ // 3 // \ // 4 // \ // 5 void Test3() { 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("Test3", pNode1, expectedPre, expectedIn, expectedPost, 5); DestroyTree(pNode1); } // 树中只有1个结点 void Test4() { BinaryTreeNode* pNode1 = CreateBinaryTreeNode(1); vector<int> expectedPre = {1}; vector<int> expectedIn = {1}; vector<int> expectedPost = {1}; Test("Test4", pNode1, expectedPre, expectedIn, expectedPost, 1); DestroyTree(pNode1); } // 树中没有结点 void Test5() { vector<int> expectedPre = {}; vector<int> expectedIn = {}; vector<int> expectedPost = {}; Test("Test5", nullptr, expectedPre, expectedIn, expectedPost, 0); } int main(int argc, char* argv[]) { Test1(); Test2(); Test3(); Test4(); Test5(); 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 基于迭代实现
3 后序遍历
后序遍历:先遍历左子树,再遍历右子树,最后遍历根节点(左-右-根)
测试代码:
// ====================测试代码==================== 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; for (int i = 0; i < length && length == expectedLength; ++i) { if (treeNodes[i] != expectedPost[i]) //遍历预测值在这里改一下就行 flag = false; } if (flag) printf("Passed.\n"); else printf("Failed.\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); } // 5 // / // 4 // / // 3 // / // 2 // / // 1 void Test2() { 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("Test2", pNode5, expectedPre, expectedIn, expectedPost, 5); DestroyTree(pNode5); } // 1 // \ // 2 // \ // 3 // \ // 4 // \ // 5 void Test3() { 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("Test3", pNode1, expectedPre, expectedIn, expectedPost, 5); DestroyTree(pNode1); } // 树中只有1个结点 void Test4() { BinaryTreeNode* pNode1 = CreateBinaryTreeNode(1); vector<int> expectedPre = {1}; vector<int> expectedIn = {1}; vector<int> expectedPost = {1}; Test("Test4", pNode1, expectedPre, expectedIn, expectedPost, 1); DestroyTree(pNode1); } // 树中没有结点 void Test5() { vector<int> expectedPre = {}; vector<int> expectedIn = {}; vector<int> expectedPost = {}; Test("Test5", nullptr, expectedPre, expectedIn, expectedPost, 0); } int main(int argc, char* argv[]) { Test1(); Test2(); Test3(); Test4(); Test5(); 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 基于迭代实现
完整代码:
// 二叉树的三种遍历 // 1.前序遍历 // 2.中序遍历 // 3.后序遍历 #include <cstdio> #include <vector> #include "BinaryTree.h" using namespace std; //注意:改动此函数即可 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); } // ====================测试代码==================== 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; for (int i = 0; i < length && length == expectedLength; ++i) { if (treeNodes[i] != expectedPre[i]) //注意:遍历预测值在这里改一下就行 flag = false; } if (flag) printf("Passed.\n"); else printf("Failed.\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); } // 5 // / // 4 // / // 3 // / // 2 // / // 1 void Test2() { 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("Test2", pNode5, expectedPre, expectedIn, expectedPost, 5); DestroyTree(pNode5); } // 1 // \ // 2 // \ // 3 // \ // 4 // \ // 5 void Test3() { 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("Test3", pNode1, expectedPre, expectedIn, expectedPost, 5); DestroyTree(pNode1); } // 树中只有1个结点 void Test4() { BinaryTreeNode* pNode1 = CreateBinaryTreeNode(1); vector<int> expectedPre = {1}; vector<int> expectedIn = {1}; vector<int> expectedPost = {1}; Test("Test4", pNode1, expectedPre, expectedIn, expectedPost, 1); DestroyTree(pNode1); } // 树中没有结点 void Test5() { vector<int> expectedPre = {}; vector<int> expectedIn = {}; vector<int> expectedPost = {}; Test("Test5", nullptr, expectedPre, expectedIn, expectedPost, 0); } int main(int argc, char* argv[]) { Test1(); Test2(); Test3(); Test4(); Test5(); return 0; }
//================================================================== // 《剑指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.