後序遍歷和層序遍歷
上一篇博文中已經通過該死的遞歸把二叉樹通過前序和中序序列給重建出來了,當然我們應該來應用這可二叉樹,以便驗證我們建立的效果。
當然,善於實踐的你可能已經知道了上篇博文中的代碼不能直接運行,因爲裏面還有其他的一些函數沒有定義而只是給出了聲明。如:
這兩個函數是實現了後序遍歷打印和層序遍歷打印的功能,下面給出簡要的闡述:
後序打印二叉樹函數定義:
我們不禁感嘆遞歸真是強大!簡單幾行代碼就可以遍歷到一棵二叉樹的所有節點,邏輯實在是簡單的讓我無話可說:
當前節點不是nullptr,我們看他的左節點是否存在,不爲nullptr,我們繼續看左節點,直到是nullptr,我們是後序,不應該先輸出root,接下來有先看右節點了!
層序打印二叉樹的函數定義:
嗯,層序遍歷一棵二叉樹,聽起來似乎很難實現,不過藉助一個隊列的數據結構,好像變得簡單了,甚至不需要遞歸!
對,不需要自己實現隊列了(你想自己實現,我雙手鼓勵)。我們首先把根節點進入隊列,並且我們還要看看這個根的下一層是否存在,存在我們繼續然他們進入隊列,然後每次循環把隊列的排頭彈出並輸出。整個循環讓他自生自滅吧,他真的會把所有的節點數據按照掃描的方式根打印出來。
下面我給出這兩個函數的定義,供大家測試:
void PrintBinTreeByPostOrder(BIN_NODE *subTree) {
//遞歸算法後序遍歷打印以subTree爲根的二叉樹
if (subTree != nullptr) {
PrintBinTreeByPostOrder(subTree->leftChild);
PrintBinTreeByPostOrder(subTree->rightChild);
std::cout << subTree->data;
}
}
void PrintBinTreeByLevelOrder(BIN_NODE *subTree) {
//運用隊列實現二叉樹的層序遍歷輸出
BIN_NODE *current = subTree;
memoryNextLevel.push(current);
while (!memoryNextLevel.empty()) {
current = memoryNextLevel.front();
memoryNextLevel.pop();
std::cout << current->data;
if (current->leftChild != nullptr) {
memoryNextLevel.push(current->leftChild);
}
if (current->rightChild != nullptr) {
memoryNextLevel.push(current->rightChild);
}
}
}
下面給出整個大程序,相信我,這次程序真的可以跑起來,,,,起碼不會出現未定義的錯誤,並且我會再次說明我的編譯器是Visual Stdio 2013,沒錯,他真的很強大。
/*
*已知前序遍歷序列和中序遍歷序列建立二叉樹
*並求其後序遍歷序列和層序遍歷序列
*/
#include <iostream>
#include <string>
#include <queue>
#include <string.h>
//二叉樹節點結構定義
struct BIN_NODE {
char data;
BIN_NODE *leftChild, *rightChild;
};
//序列存儲變量
//用戶輸入字符串測試
char preSequence[100];
char inSequence[100];
//指定字符串測試
//char *preSequence = "GDAFEMHZ";
//char* inSequence = "ADEFGHMZ";
//樹根定義
BIN_NODE *tree;
//存儲下一層節點的隊列
std::queue<BIN_NODE *> memoryNextLevel;
//函數聲明
void PrintBinTreeByPostOrder(BIN_NODE *subTree); //後序打印二叉樹數據域
void PrintBinTreeByLevelOrder(BIN_NODE *subTree); //層序打印二叉樹數據域
//通過前序、中序序列建立二叉樹
BIN_NODE * CreateBinTreeByPreInOrder(char* preSeq, char* InSeq, int subStrLen);
int main()
{
int groupsAmount = 0;
std::cin >> groupsAmount;
while (groupsAmount--) {
std::cin >> preSequence >> inSequence;
tree = CreateBinTreeByPreInOrder(preSequence, inSequence, strlen(inSequence));
PrintBinTreeByPostOrder(tree);
std::cout << std::endl;
PrintBinTreeByLevelOrder(tree);
std::cout << std::endl;
}
return 0;
}
//函數定義
BIN_NODE * CreateBinTreeByPreInOrder(char* preSeq, char* InSeq, int subStrLen) {
if (0 == subStrLen) {
return nullptr;
}
BIN_NODE *node = new BIN_NODE;
if (node == nullptr) {
std::cerr << "error" << std::endl;
exit(1);
}
node->data = *preSeq;
//前序相應元素在中序中的下標索引值
int rootIndex = 0;
//求解這個索引值
for (; rootIndex < subStrLen; rootIndex ++) {
if (InSeq[rootIndex] == *preSeq) {
break;
}
}
node->leftChild = CreateBinTreeByPreInOrder(preSeq + 1, InSeq, rootIndex);
node->rightChild = CreateBinTreeByPreInOrder(preSeq + rootIndex + 1,
InSeq + rootIndex + 1, subStrLen - (rootIndex + 1));
return node;
}
void PrintBinTreeByPostOrder(BIN_NODE *subTree) {
//遞歸算法後序遍歷打印以subTree爲根的二叉樹
if (subTree != nullptr) {
PrintBinTreeByPostOrder(subTree->leftChild);
PrintBinTreeByPostOrder(subTree->rightChild);
std::cout << subTree->data;
}
}
void PrintBinTreeByLevelOrder(BIN_NODE *subTree) {
//運用隊列實現二叉樹的層序遍歷輸出
BIN_NODE *current = subTree;
memoryNextLevel.push(current);
while (!memoryNextLevel.empty()) {
current = memoryNextLevel.front();
memoryNextLevel.pop();
std::cout << current->data;
if (current->leftChild != nullptr) {
memoryNextLevel.push(current->leftChild);
}
if (current->rightChild != nullptr) {
memoryNextLevel.push(current->rightChild);
}
}
}
如果你覺得他的輸入輸出讓你一頭霧水,也許你需要下面這測試知道(我想的很全面的)
我可沒有騙你!
好,二叉樹的經典問題就分析到裏,當然後面少不了更多的問題。