九度OJ-題目1523:從上往下列印二叉樹
阿新 • • 發佈:2019-02-16
題目連結地址:
題目描述:
從上往下打印出二叉樹的每個節點,同層節點從左至右列印。
輸入:
輸入可能包含多個測試樣例,輸入以EOF結束。
對於每個測試案例,輸入的第一行一個整數n(1<=n<=1000, :n代表將要輸入的二叉樹元素的個數(節點從1開始編號)。接下來一行有n個數字,代表第i個二叉樹節點的元素的值。接下來有n行,每行有一個字母Ci。
Ci=’d’表示第i個節點有兩子孩子,緊接著是左孩子編號和右孩子編號。
Ci=’l’表示第i個節點有一個左孩子,緊接著是左孩子的編號。
Ci=’r’表示第i個節點有一個右孩子,緊接著是右孩子的編號。
Ci=’z’表示第i個節點沒有子孩子。
輸出:
對應每個測試案例,
按照從上之下,從左至右打印出二叉樹節點的值。
樣例輸入:
7
8 6 5 7 10 9 11
d 2 5
d 3 4
z
z
d 6 7
z
z
樣例輸出:
8 6 10 5 7 9 11
解題思路:
從上往下打印出二叉樹的每個節點,同層節點從左至右列印,很明顯這是二叉樹的層序遍歷。深井冰人思維廣,很快我就發現二叉樹的層序遍歷和圖的廣度優先遍歷很相似啊。於是就模仿圖的廣度優先遍歷想(YY)出了以下演算法:
(1) 申請一個佇列用於儲存二叉樹的結點,將二叉樹的根結點插入到佇列末尾;
(2) 彈出佇列的隊首元素,如果該元素還有左右孩子,則將其左右孩子也依次插入到佇列末尾;
(3) 重複步驟(2),當佇列為空時,二叉樹的層序遍歷操作就完成了。
AC程式碼如下:
// 二叉樹的層序遍歷 #include<stdio.h> #include<queue> using namespace std; #define MAX 1001 // 定義二叉樹的結點 typedef struct Node { bool isRoot; // 標記該結點是否為二叉樹的根結點 int data; // 資料域 Node * lchild; // 左孩子 Node * rchild; // 右孩子 }BiTreeNode; // 定義二叉樹中的各個結點 BiTreeNode biTreeNode[MAX]; /** * 構造有n個結點的二叉樹 * @param n 表示二叉樹的結點個數 * @return root 返回二叉樹的根結點 */ BiTreeNode * createBinaryTree(int n) { BiTreeNode * root = NULL; char Ci; int i; int data; // 輸入的二叉樹結點的資料 int leftChild; // 二叉樹結點的左孩子編號 int rightChild; // 二叉樹結點的右孩子編號 // (1)初始時各個結點都被看成是隻有一個結點的二叉樹 for(i = 1;i <= n;i++) { scanf("%d",&data); biTreeNode[i].data = data; biTreeNode[i].lchild = NULL; biTreeNode[i].rchild = NULL; biTreeNode[i].isRoot = true; } // (2)構建各個結點的孩子 for(i = 1;i <= n;i++) { while(getchar() != '\n'); // 清除前一個scanf留下的多餘的字元 scanf("%c",&Ci); switch(Ci) { case 'd': scanf("%d%d",&leftChild,&rightChild); biTreeNode[i].lchild = &biTreeNode[leftChild]; biTreeNode[i].rchild = &biTreeNode[rightChild]; biTreeNode[leftChild].isRoot = false; biTreeNode[rightChild].isRoot = false; break; case 'l': scanf("%d",&leftChild); biTreeNode[i].lchild = &biTreeNode[leftChild]; biTreeNode[leftChild].isRoot = false; break; case 'r': scanf("%d",&rightChild); biTreeNode[i].rchild = &biTreeNode[rightChild]; biTreeNode[rightChild].isRoot = false; break; case 'z': break; default: break; }//switch }//for //(3)尋找二叉樹的根結點,如果某個結點沒有父結點,則認為該結點是二叉樹的根結點 for(i = 1;i <= n;i++) { if(true == biTreeNode[i].isRoot) { root = &biTreeNode[i]; break; } } return root; } /** * 採用類似於廣度優先遍歷的方法來層序遍歷二叉樹 * @param root 二叉樹的根結點 * @return void */ void travLevelBinaryTree(BiTreeNode * root) { BiTreeNode * cur; // 當前正在被遍歷的二叉樹結點 queue <BiTreeNode *> q; q.push(root); // 將二叉樹的根結點插入到佇列末尾 while(false == q.empty()) { cur = q.front(); q.pop(); if(cur == root) { printf("%d",cur -> data); // 輸出當前結點的值 } else { printf(" %d",cur -> data); // 輸出當前結點的值 } if(NULL != cur -> lchild) // 將當前結點的左孩子插入到佇列末尾 { q.push(cur -> lchild); } if(NULL != cur -> rchild) // 將當前結點的右孩子插入到佇列末尾 { q.push(cur -> rchild); } } printf("\n"); } int main() { BiTreeNode * root; int n; while(EOF != scanf("%d",&n)) { root = createBinaryTree(n); travLevelBinaryTree(root); // 層序遍歷二叉樹 } return 0; } /************************************************************** Problem: 1523 User: blueshell Language: C++ Result: Accepted Time:0 ms Memory:1076 kb ****************************************************************/