二叉樹的遍歷c++程式碼實現
二叉樹的遍歷是指從根結點出發,按照某種次序依次訪問二叉樹中所有結點,使得每個結點被訪問一次
且僅被訪問一次。
二叉樹的遍歷方式常用的有四種:前序遍歷、中序遍歷、後序遍歷和層序遍歷。
二叉樹結點的定義程式碼如下:
//Definition for binary tree
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
前序遍歷:簡單來說就是:根->左->右。
規則:若二叉樹為空,則空操作返回,否則先訪問根結點,然後前序遍歷左子樹,再前序遍歷右子樹。
c++程式碼實現:
//前序遍歷二叉樹:根--左--右
void preScanf(TreeNode* t)
{
if (t == NULL)
{
return;
}
cout << t->val <<" ";
preScanf(t->left);
preScanf(t->right);
}
中序遍歷:簡單來說就是:左->根->右。
規則:若二叉樹為空,則空操作返回,否則從根結點開始,先中序遍歷根結點的左子樹,然後是訪問
根結點,最後中序遍歷右子樹。
c++程式碼如下:
//中序遍歷二叉樹:左---根---右 void middleScanf(TreeNode* t) { if (t == NULL) { return; } middleScanf(t->left); cout << t->val << " "; middleScanf(t->right); }
後序遍歷:簡單來說就是:左->右->根。
規則:若二叉樹為空,則空操作返回,否則從根結點開始,先後序遍歷根結點的左子樹,再後序遍歷
根結點的右子樹,最後訪問根結點。
c++程式碼如下:
//後序遍歷二叉樹:左---右---根
void backScanf(TreeNode* t)
{
if (t == NULL)
{
return;
}
backScanf(t->left);
backScanf(t->right);
cout << t->val <<" ";
}
層序遍歷:從上到下,從左到右。
規則:若二叉樹為空,則空操作返回,否則從二叉樹的第一層也就是根結點開始訪問,從上而下逐層遍歷,
在同一層中,按從左到右的順序對結點逐個訪問。
程式碼思路講解:若要實現按層遍歷,那麼應該先訪問根結點,然後再訪問遍歷結點的兩個子節點,放入容器,
按照從左到右的順序遍歷到左子節點時就把其的兩個子節點放到容器,最後輸出的時候,就是從容器中按照順序輸出,
先進先出,所以想到可以用佇列做為資料容器。
從上到下列印二叉樹的規律:每一次列印一個節點的時候,如果該結點有子結點,則把該結點的子結點放到一個佇列的末尾,
接下來從佇列的頭部取出最早進入佇列的結點,重複輸出,直至佇列中所有結點都被打印出來。
c++程式碼如下:
//層序遍歷二叉樹:從上到下,從左到右
void fromTopToBottomScanf(TreeNode* t)
{
if (t==NULL)
{
return;
}
deque<TreeNode*> dequeTreeNode;
dequeTreeNode.push_back(t);
while (dequeTreeNode.size())
{
TreeNode* pNode = dequeTreeNode.front(); //依次取出佇列中的頭部元素進行列印
dequeTreeNode.pop_front(); //
cout << pNode->val << " ";
if (pNode->left)
{
dequeTreeNode.push_back(pNode->left);
}
if (pNode->right)
{
dequeTreeNode.push_back(pNode->right);
}
}
}
下面結合具體的例子說明:
程式設計實現:輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6},則重建二叉樹並返回。
由前序遍歷和中序遍歷結果重構二叉樹,並把重構出來的二叉樹分別採用以上的四種遍歷方式進行輸出。
c++程式碼實現如下:
#include <iostream>
#include <vector>
#include <deque>
using namespace std;
//Definition for binary tree
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
class Solution {
public:
TreeNode* reConstructBinaryTree(vector<int> pre, vector<int> vin) {
if (pre.size() == 0 || vin.size() == 0)
return NULL;
vector<int>::iterator preStartIter = pre.begin();
vector<int>::iterator preEndIter = pre.end()-1;
vector<int>::iterator vinStartIter = vin.begin();
vector<int>::iterator vinEndIter = vin.end()-1;
return constructCore(preStartIter,preEndIter,vinStartIter,vinEndIter);
}
private:
TreeNode* constructCore(vector<int>::iterator preStartIter,
vector<int>::iterator preEndIter,vector<int>::iterator vinStartIter,vector<int>::iterator vinEndIter){
int rootValue = *preStartIter;
TreeNode* root = new TreeNode(rootValue);
//如果只有一個根節點,那麼返回根節點
if (preStartIter==preEndIter)
{
if (vinStartIter==vinEndIter && *preStartIter==*vinStartIter)
{
return root;
}
else
{
throw std::exception("invalid input!");
}
}
//在中序遍歷結果中去查詢根節點值,找到左右子樹分割點位置
vector<int>::iterator rootInVin = vinStartIter;
while (rootInVin!=vinEndIter && *rootInVin!=rootValue)
{
++rootInVin;
}
//求左子樹的長度
int leftLength = rootInVin - vinStartIter;
vector<int>::iterator preLeftEnd = preStartIter + leftLength;
if (leftLength>0)
{
//構建左子樹
root->left=constructCore(preStartIter+1, preLeftEnd, vinStartIter, rootInVin-1);
}
if (leftLength<preEndIter-preStartIter) //如果存在右子樹,則遞迴建立右子樹
{
//構建右子樹
root->right = constructCore(preLeftEnd + 1, preEndIter, rootInVin + 1, vinEndIter);
}
return root;
}
};
//前序遍歷二叉樹:根--左--右
void preScanf(TreeNode* t)
{
if (t == NULL)
{
return;
}
cout << t->val <<" ";
preScanf(t->left);
preScanf(t->right);
}
//中序遍歷二叉樹:左---根---右
void middleScanf(TreeNode* t)
{
if (t == NULL)
{
return;
}
middleScanf(t->left);
cout << t->val << " ";
middleScanf(t->right);
}
//後序遍歷二叉樹:左---右---根
void backScanf(TreeNode* t)
{
if (t == NULL)
{
return;
}
backScanf(t->left);
backScanf(t->right);
cout << t->val <<" ";
}
//層序遍歷二叉樹:從上到下,從左到右
void fromTopToBottomScanf(TreeNode* t)
{
if (t==NULL)
{
return;
}
deque<TreeNode*> dequeTreeNode;
dequeTreeNode.push_back(t);
while (dequeTreeNode.size())
{
TreeNode* pNode = dequeTreeNode.front(); //依次取出佇列中的頭部元素進行列印
dequeTreeNode.pop_front(); //
cout << pNode->val << " ";
if (pNode->left)
{
dequeTreeNode.push_back(pNode->left);
}
if (pNode->right)
{
dequeTreeNode.push_back(pNode->right);
}
}
}
int main()
{
Solution s;
vector<int> pre = { 1, 2, 4, 7, 3, 5, 6, 8 };
vector<int> vin = { 4, 7, 2, 1, 5, 3, 8, 6 };
TreeNode *t;
t = s.reConstructBinaryTree(pre, vin);
cout << "前序遍歷二叉樹序列為:" << endl;
preScanf(t);
cout << endl<<"中序遍歷二叉樹序列為:"<< endl;
middleScanf(t);
cout << endl<<"後序遍歷二叉樹序列為:" << endl;
backScanf(t);
cout << endl << "後序遍歷二叉樹序列為:" << endl;
fromTopToBottomScanf(t);
cout << endl;
return 0;
}
程式的輸出結果如下: