簡介
前面介紹過二叉樹的數據結構,它的邏輯很簡單,除了根結點之外每個結點只有一個父節點,除了葉結點之外所有的結點都有一個或多個子節點。父和子之間用指針連接。
二叉樹有三種變量方式:
-前序遍歷:根左右
-中序遍歷:左根右
-後序遍歷:左右根
題目1:重建二叉樹
輸入某二叉樹的前 序遍歷和中序遍歷的結果,重建該二叉樹
struct BinaryTreeNode//結點結構 { int _value; BinaryTreeNode* _left; BinaryTreeNode* _right; BinaryTreeNode(const int&x) { _value = x; _left = NULL; _right = NULL; } }; BinaryTreeNode* Construct(int * prevOrder, int *inOrder, int length) { if (prevOrder == NULL || inOrder == NULL || length == 0) return; return ConstructCore(prevOrder,prevOrder+length-1,inOrder,inOrder+length-1) } BinaryTreeNode*ConstructCore(int* PrevHead, int*prevTail, int*inHead, int*inTail) { //前序遍歷的第一個節點即爲根結點 BinaryTreeNode* root = new BinaryTreeNode(PrevHead[0]); //只有一個節點 if (PrevHead == prevTail) { if (inHead == inTail) return root; else throw std::exception("Invalid inPut");//拋出異常 } //在中序結點中找到根結點的值 int *InorderRoot = inHead; while (InorderRoot<=inTail&&InorderRoot != PrevHead) { InorderRoot++; } if (InorderRoot == inTail&&*InorderRoot != PrevHead[0]) throw std::exception("Invalid input"); int leftLength = InorderRoot - inHead; int* leftPrevOrderTail = PrevHead + leftLength; if (leftLength > 0) { //構建左子樹 root->_left = ConstructCore(PrevHead + 1, leftPrevOrderTail, inHead, InorderRoot - 1); } if (leftLength < prevTail - PrevHead) { //構建右子樹 root->_right = ConstructCore(leftPrevOrderTail + 1, prevTail, InorderRoot + 1, inTail); } return root; }
題目二:二叉樹的鏡像
先前序遍歷這棵樹的結點,若遍歷到的結點有子節點,就交換這個兩個子節點,當交換完成所有非葉子結點的左右結點之後,就得到數的鏡像
void MirrorRecursively(BinaryTreeNode *pRoot) { if ((pRoot == NULL)||(pRoot->m_pLeft==NULL&&pRoot->m_pRight==NULL)) return; swap(pRoot->m_pLeft, pRoot->m_pRight); if (pRoot->m_pLeft) MirrorRecursively(pRoot->m_pLeft); if (pRoot->m_pRight) MirrorRecursively(pRoot->m_pRight); }
題目三:輸入兩顆二叉樹A和B,判斷B不是A的子結構
bool HasSubTree(BinaryTreeNode*pRoot1, BinaryTreeNode*pRoot2) { BinaryTreeNode* pcur1 = pRoot1; BinaryTreeNode* pcur2 = pRoot2; bool result = false; if (pRoot1 != NULL || pRoot2 != NULL) { if (pcur1->m_value == pcur2->m_value) result = DoseTree1HaveTree2(pcur1, pcur2); if (!result) result = HasSubTree(pcur1->m_pLeft, pcur2); if (!result) result = HasSubTree(pcur1->m_pRight, pcur2); } return result; } bool DoseTree1HaveTree2(BinaryTreeNode* pRoot1, BinaryTreeNode* pRoot2) { if (pRoot2 == NULL) return true; if (pRoot2 == NULL) return false; if (pRoot1->m_value != pRoot2->m_value) return false; return DoseTree1HaveTree2(pRoot1->m_pLeft, pRoot1->m_pLeft) && DoseTree1HaveTree2(pRoot1->m_pRight, pRoot2->m_pRight); }
題目四:層序遍歷二叉樹
void PrintLevelOrder(BinaryTreeNode<T>*root) { if (root == NULL) return; queue<BinaryTreeNode<T>*>q1; q1.push(root); while (q1.size() != 0) { if (q1.front()->_left) { q1.push(q1.front()->_left); } if (q1.front()->_right) { q1.push(q1.front()->_right); } cout << q1.front()->_value << " "; q1.pop(); } }
題目五:前序非遞歸實現
void PrintPrevOrder(BinaryTreeNode<T>root) { if(root==NULL) return; stack<BinaryTreeNode<T>*>s; s.push(root); while(s.size()>0) { BinaryTreeNode<T>*cur=s.top(); s.pop(); cout<<cur->_value<<" "; if(root->_right!=NULL) s.push(root->_right); if(root->_left!=NULL) s.push(root->_left); } }
題目六:中序的非遞歸實現
void PrintInOrder(BinaryTreeNode<T>root) { stack<BinaryTreeNode<T>*>s; BinaryTreeNode<T>*cur=root; while(cur||s.size>0) { s.push(cur); while(cur->_left) { s.pusu(cur->_left); cur=cur->_left; } cout<<s.top()->_value<<" "; cur=s.top()->_right; s.pop(); } }
題目七:後序的非遞歸實現
void PrintPostOrder(BinaryTreeNode<T>*root) { stack<BinaryTreeNode<T>*>s; BinaryTreeNode<T>*cur = root; BinaryTreeNode<T>*prev = NULL; while (cur || s.size() > 0) { while (cur != NULL) { s.push(cur); cur = cur->_left; } cur = s.top(); if (cur->_right == NULL || cur->_right == prev) { cout << cur->_value << " "; prev = cur; cur = NULL; s.pop(); } else { cur = cur->_right; } } }
題目八:二叉搜索樹的後序遍歷
輸入一個整數數組,判斷該數組是不是某二叉樹的後序遍歷結果,如果是返回true,否則返回false
bool VerifySquenceOfBST(int sequence[], int length) { if (sequence == NULL || length <= 0) return false; int root = sequence[length - 1]; size_t i = 0; for ( i = 0; i < length - 1; i++) { if (sequence[i]>root) break; } size_t j = i; for (; j < length; j++) { if (sequence[j] < root) return false; } bool left = true; left = VerifySquenceOfBST(sequence, i); bool right = true; right = VerifySquenceOfBST(sequence + i, length - i - i); return left&&right; }
題目九:二叉樹中和爲某一值的路徑
輸入一個二叉樹和一個整數,打印出二叉樹中結點值的和爲輸入整數的所有路徑,從樹的根開始往下一直到葉形成一條路徑
void Findpath(BinatryTreeNode<T>*root, T sum) { if (root == NULL) return; vector<BinatryTreeNode<T>*> path; int curSum = 0; _FindPath(root, sum, path, curSum); } private: void _FindPath(BinatryTreeNode<T>*root, const T&sum, vector<BinaryTreeNode<T>*>&path, T&curSum) { curSum_ += root->_value; path.push_back(root); //如果爲葉結點且路徑值相等則輸出路徑 bool IsLeaf = root->_right == NULL&&root->_left == NULL; if (curSum == sum&&IsLeaf) { for (size_t i = 0; i < path.size(); i++) { cout << path[i]->_value << " "; } } //若不是葉結點遍歷至葉結點 if (root->_left != NULL) _FindPath(root->_left, sum, path, curSum); if (root->_right != NULL) _FindPath(root->_right, sum, path, curSum); curSum -= root->_value; path.pop_back(); }