1. 程式人生 > >九度OJ-題目1523:從上往下列印二叉樹

九度OJ-題目1523:從上往下列印二叉樹

題目連結地址:

題目描述:
從上往下打印出二叉樹的每個節點,同層節點從左至右列印。

輸入:
輸入可能包含多個測試樣例,輸入以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
****************************************************************/