1. 程式人生 > >九度OJ-題目1521:二叉樹的映象

九度OJ-題目1521:二叉樹的映象

題目連結地址:

題目描述:
輸入一個二叉樹,輸出其映象。


輸入:
輸入可能包含多個測試樣例,輸入以EOF結束。
對於每個測試案例,輸入的第一行為一個整數n(0<=n<=1000,n代表將要輸入的二叉樹節點的個數(節點從1開始編號)。接下來一行有n個數字,代表第i個二叉樹節點的元素的值。接下來有n行,每行有一個字母Ci。
Ci=’d’表示第i個節點有兩子孩子,緊接著是左孩子編號和右孩子編號。
Ci=’l’表示第i個節點有一個左孩子,緊接著是左孩子的編號。
Ci=’r’表示第i個節點有一個右孩子,緊接著是右孩子的編號。
Ci=’z’表示第i個節點沒有子孩子。

輸出:
對應每個測試案例,
按照前序輸出其孩子節點的元素值。
若為空輸出NULL。

樣例輸入:
7
8  6  10  5  7  9  11
d  2  3
d  4  5
d  6  7
z
z
z
z

樣例輸出:
8  10  11  9  6  7  5

解題思路:

解法一 將二叉樹的前序遍歷順序改為“中右左”
題目只要求輸出二叉樹映象的前序遍歷序列,所以只需要在前序遍歷二叉樹的時候將遍歷順序由原來的“中左右”改為"中右左"即可。
AC程式碼如下:

// 解法一:仔細分析二叉樹的定義,就可以知道將原二叉樹所有結點的左右子樹進行對換即可得到二叉樹的映象
// 但是題目只要求輸出二叉樹映象的前序遍歷序列,所以只需要在前序遍歷二叉樹的時候將遍歷順序改為"中右左"即可
#include<stdio.h>
#define MAX 1001
 
// 定義二叉樹的結點
typedef struct BNode
{
   bool isRootNode;       // 標記該結點是否為根結點
   int data;              // 資料域
   BNode * lchild;        // 左子樹
   BNode * rchild;        // 右子樹
}BinaryTreeNode;
 
BinaryTreeNode biTreeNode[MAX];      // 定義二叉樹的結點陣列
 
/**
* 構造有n個結點的二叉樹
* @param n  表示二叉樹的結點個數
* @return root  返回二叉樹的根結點
*/
BinaryTreeNode * createBinaryTree(int n)
{
   BinaryTreeNode * root = NULL;     // root指向二叉樹的根節點
   if(0 == n)                        // 對於空二叉樹,直接返回NULL
        return root;
   char Ci;                          // Ci代表當前結點的孩子結點情況
   int i;
   int data;                         // 二叉樹結點的資料域
   int leftChild,rightChild;         // 二叉樹結點的左孩子和右孩子
   // 先構造各個結點,初始狀態下,每個結點都看成是隻有一個結點的二叉樹
   for(i = 1;i <= n;i++)
   {
      scanf("%d",&data);
      biTreeNode[i].data = data;
      biTreeNode[i].lchild = NULL;
      biTreeNode[i].rchild = NULL;
      biTreeNode[i].isRootNode = true;
   }
   // 根據各個結點之間的連結關係構造二叉樹
   for(i = 1;i <= n;i++)
   {
      char ch;
      while((ch = getchar()) != '\n');  //用getchar吃掉前面scanf輸入的'\n'和該'\n'之前的多餘字元
      scanf("%c",&Ci);
      switch(Ci)
      {
          case 'd':
               scanf("%d%d",&leftChild,&rightChild);
               biTreeNode[i].lchild = &biTreeNode[leftChild];
               biTreeNode[i].rchild = &biTreeNode[rightChild];
               biTreeNode[leftChild].isRootNode = false;       // 表示結點leftChild不是二叉樹的根結點
               biTreeNode[rightChild].isRootNode = false;      // 表示結點rightChild不是二叉樹的根結點
               break;
          case 'l':
               scanf("%d",&leftChild);
               biTreeNode[i].lchild = &biTreeNode[leftChild];
               biTreeNode[i].rchild = NULL;
               biTreeNode[leftChild].isRootNode = false;       // 表示結點leftChild不是二叉樹的根結點
               break;
          case 'r':
               scanf("%d",&rightChild);
               biTreeNode[i].lchild = NULL;
               biTreeNode[i].rchild = &biTreeNode[rightChild];
               biTreeNode[rightChild].isRootNode = false;      // 表示結點rightChild不是二叉樹的根結點
               break;
          case 'z':
               biTreeNode[i].lchild = NULL;
               biTreeNode[i].rchild = NULL;
               break;
          default:
               break;
      }//switch
   }//for
   // 如果某個結點不是任何結點的孩子結點,則該結點就是根結點
   for(i = 1;i <= n;i++)
   {
      if(true == biTreeNode[i].isRootNode)
      {
          root = &biTreeNode[i];                          // root指向根結點
          break;
      }
   }
   return root;
}
 
/**
* 按照"中右左"的順序前序遍歷二叉樹就能得到二叉樹映象的前序遍歷序列
* @param root  二叉樹的根結點
* @return void
*/
void preOrderTraverseImage(BinaryTreeNode * root)
{
   if(NULL == root)
   return;
   printf(" %d",root -> data);
   preOrderTraverseImage(root -> rchild);
   preOrderTraverseImage(root -> lchild);
}
 
int main()
{
    int n;
    BinaryTreeNode * root;
    while(EOF != scanf("%d",&n))
    {
        root = createBinaryTree(n);
        if(NULL == root)
        {
           printf("NULL\n");
        }
 
        else
        {
           printf("%d",root -> data);
           preOrderTraverseImage(root -> rchild);
           preOrderTraverseImage(root -> lchild);
           printf("\n");
        }
    }
    return 0;
}
/**************************************************************
    Problem: 1521
    User: blueshell
    Language: C++
    Result: Accepted
    Time:0 ms
    Memory:1044 kb
****************************************************************/

解法二 將原二叉樹所有結點的左右孩子結點進行對換
仔細分析二叉樹映象的定義,可以發現將二叉樹中所有結點的左右孩子結點進行對換就可以得到二叉樹映象。
這道題目還有一個地方需要注意:就是在構造二叉樹的過程中,第1個結點不一定就是二叉樹的根結點,我開始就以為第1個結點就是二叉樹的根結點,結果一直Wrong Answer。。。構造二叉樹的步驟分為三步:
(1)將各個結點都看成是隻有根結點而沒有左右孩子的小二叉樹,而所需要構造的二叉樹則看成是一棵空樹;
(2)確定所要構造二叉樹中每個結點的左右孩子結點,這個操作會將每個結點都併入到所要構造的二叉樹中;
(3)執行完步驟(2)後,再找出沒有父結點的結點,該結點就是二叉樹的根結點了。


  AC程式碼如下:

// 解法二:仔細分析二叉樹的定義,就可以知道將原二叉樹所有結點的左右孩子進行對換即可得到二叉樹的映象
#include<stdio.h>
#define MAX 1001
 
// 定義二叉樹的結點
typedef struct BNode
{
   bool isRootNode;       // 標記該結點是否為根結點
   int data;              // 資料域
   BNode * lchild;        // 左子樹
   BNode * rchild;        // 右子樹
}BinaryTreeNode;
 
BinaryTreeNode biTreeNode[MAX];      // 定義二叉樹的結點陣列
 
/**
* 構造有n個結點的二叉樹
* @param n  表示二叉樹的結點個數
* @return root  返回二叉樹的根結點
*/
BinaryTreeNode * createBinaryTree(int n)
{
   BinaryTreeNode * root = NULL;     // root指向二叉樹的根節點
   if(0 == n)                        // 對於空二叉樹,直接返回NULL
        return root;
   char Ci;                          // Ci代表當前結點的孩子結點情況
   int i;
   int data;                         // 二叉樹結點的資料域
   int leftChild,rightChild;         // 二叉樹結點的左孩子和右孩子
   // 先構造各個結點,初始狀態下,每個結點都看成是隻有一個結點的二叉樹
   for(i = 1;i <= n;i++)
   {
      scanf("%d",&data);
      biTreeNode[i].data = data;
      biTreeNode[i].lchild = NULL;
      biTreeNode[i].rchild = NULL;
      biTreeNode[i].isRootNode = true;
   }
   // 根據各個結點之間的連結關係構造二叉樹
   for(i = 1;i <= n;i++)
   {
      char ch;
      while((ch = getchar()) != '\n');  //用getchar吃掉前面scanf輸入的'\n'和該'\n'之前的多餘字元
      scanf("%c",&Ci);
      switch(Ci)
      {
          case 'd':
               scanf("%d%d",&leftChild,&rightChild);
               biTreeNode[i].lchild = &biTreeNode[leftChild];
               biTreeNode[i].rchild = &biTreeNode[rightChild];
               biTreeNode[leftChild].isRootNode = false;       // 表示結點leftChild不是二叉樹的根結點
               biTreeNode[rightChild].isRootNode = false;      // 表示結點rightChild不是二叉樹的根結點
               break;
          case 'l':
               scanf("%d",&leftChild);
               biTreeNode[i].lchild = &biTreeNode[leftChild];
               biTreeNode[i].rchild = NULL;
               biTreeNode[leftChild].isRootNode = false;       // 表示結點leftChild不是二叉樹的根結點
               break;
          case 'r':
               scanf("%d",&rightChild);
               biTreeNode[i].lchild = NULL;
               biTreeNode[i].rchild = &biTreeNode[rightChild];
               biTreeNode[rightChild].isRootNode = false;      // 表示結點rightChild不是二叉樹的根結點
               break;
          case 'z':
               biTreeNode[i].lchild = NULL;
               biTreeNode[i].rchild = NULL;
               break;
          default:
               break;
      }//switch
   }//for
   // 如果某個結點不是任何結點的孩子結點,則該結點就是根結點
   for(i = 1;i <= n;i++)
   {
      if(true == biTreeNode[i].isRootNode)
      {
          root = &biTreeNode[i];                          // root指向根結點
          break;
      }
   }
   return root;
}
 
/**
* 將原二叉樹所有結點的左右孩子進行對換得到二叉樹的映象
* @param root  二叉樹的根結點
* @return void
*/
void makeBinaryTreeImage(BinaryTreeNode * root)
{
  if(NULL == root)
  return;
  BinaryTreeNode * temp;
  temp = root -> lchild;
  root -> lchild = root -> rchild;
  root -> rchild = temp;
  makeBinaryTreeImage(root -> lchild);
  makeBinaryTreeImage(root -> rchild);
}
 
/**
* 前序遍歷二叉樹映象
* @param root  二叉樹的根結點
* @return void
*/
void preOrderTraverseImage(BinaryTreeNode * root)
{
   if(NULL == root)
   return;
   printf(" %d",root -> data);
   preOrderTraverseImage(root -> lchild);
   preOrderTraverseImage(root -> rchild);
}
 
int main()
{
    int n;
    BinaryTreeNode * root;
    while(EOF != scanf("%d",&n))
    {
        root = createBinaryTree(n);
        if(NULL == root)
        {
           printf("NULL\n");
        }
 
        else
        {
           makeBinaryTreeImage(root);
           printf("%d",root -> data);
           preOrderTraverseImage(root -> lchild);
           preOrderTraverseImage(root -> rchild);
           printf("\n");
        }
    }
    return 0;
}
 
/**************************************************************
    Problem: 1521
    User: blueshell
    Language: C++
    Result: Accepted
    Time:0 ms
    Memory:1044 kb
****************************************************************/

相關推薦

OJ-題目1521映象

題目連結地址: 題目描述: 輸入一個二叉樹,輸出其映象。 輸入: 輸入可能包含多個測試樣例,輸入以EOF結束。 對於每個測試案例,輸入的第一行為一個整數n(0<=n<=1000,n代表將要輸入的二叉樹節點的個數(節點從1開始編號)。接下來一行有n個數字,

題目1521映象

時間限制:1 秒記憶體限制:128 兆特殊判題:否提交:1026解決:265題目描述: 輸入一個二叉樹,輸出其映象。輸入: 輸入可能包含多個測試樣例,輸入以EOF結束。 對於每個測試案例,輸入的第一行為一個整數n(0<=n<=1000,n代表將要輸入的二叉樹節

OJ-題目1009搜索

提交 二叉排序樹 軟件 amp cpp creat .com xheditor ear 題目1009:二叉搜索樹 從如今開始打算重新啟動刷題征程。程序猿的人生不須要解釋! 這次撇開poj hoj等難度較大的oj系統,從九度入手(已經非常長時間沒寫過代碼

OJ-題目1009搜尋

題目1009:二叉搜尋樹         從現在開始打算重啟刷題征程。程式設計師的人生不需要解釋! 這次撇開poj hoj等難度較大的oj系統,從九度入手(已經很長時間沒寫過程式碼了),主要先“叫醒” 沉睡依舊的大腦。唉~真的很長時間沒寫部落格,沒寫程式碼了,只能加油吧!

OJ題目1201排序

紀念一下終於在二叉樹上的程式碼準確率,但還是在給root分配空間的時候忘記要寫了  悲劇 還沒看到提示要考慮忽略重複元素,這個好解決 題目描述:     輸入一系列整數,建立二叉排序數,並進行前

OJ-題目1523從上往下列印

題目連結地址: 題目描述:從上往下打印出二叉樹的每個節點,同層節點從左至右列印。 輸入:輸入可能包含多個測試樣例,輸入以EOF結束。對於每個測試案例,輸入的第一行一個整數n(1<=n<=1000, :n代表將要輸入的二叉樹元素的個數(節點從1開始編號)。接下

題目1541

二叉樹的操作,旋轉操作就按他給的圖來進行吧,需要細心,要把各節點的兒子父親安排的妥妥的.還有不知道他是一棵還是多棵二叉樹... #include<stdio.h> #include<string.h> #include<algorithm

OJ 題目1204農夫、羊、菜和狼的故事

pla pan wol 題目 r+ ear play struct tab 思路:廣度 優先 記錄路徑長度 但是題目的意思好像是要記錄具體路徑 下次再搞吧 題目描述: 有一個農夫帶一只羊、一筐菜和一只狼過河.果沒有農夫看管,則狼要吃羊,羊要吃菜.但是船很小,只

OJ題目1089數字反轉

題目描述:     12翻一下是21,34翻一下是43,12+34是46,46翻一下是64,現在又任意兩個正整數,問他們兩個數反轉的和是否等於兩個數的和的反轉。 輸入:     第一行一個正整數表示測試資料的個數n。     只有n行,每行兩個正整數a和b(0<a,b<=10000)。 輸出

筆記之 1467排序

題目1467:二叉排序樹 時間限制:1 秒 記憶體限制:128 兆 特殊判題:否 提交:1292 解決:518 題目描述:         二叉排序樹,也稱為二叉查詢樹。可以是一顆空樹,也可以是一顆具有如下特性的非空二叉樹:         1

OJ 題目1014排名

題目描述:     今天的上機考試雖然有實時的Ranklist,但上面的排名只是根據完成的題數排序,沒有考慮每題的分值,所以並不是最後的排名。給定錄取分數線,請你寫程式找出最後通過分數線的考生,並將他們的成績按降序列印。 輸入:     測試輸入包含若干場考試的資訊。每場

oj 題目120810進位制 VS 2進位制

參考了 根據參考1有 #include <cstdio> #include <cstring> #define MAXN 4000 int main(){ int to[MAXN]; int from[MAXN];

OJ-題目1019簡單計算器

題目描述:     讀入一個只包含 +, -, *, / 的非負整數計算表示式,計算該表示式的值。 輸入:     測試輸入包含若干測試用例,每個測試用例佔一行,每行不超過200個字元,整數和運算子之間用一個空格分隔。沒有非法表示式。當一行中只有0時輸入結束,相應的結果

OJ-題目1214醜數

題目連結地址: 題目描述:把只包含因子2、3和5的數稱作醜數(Ugly Number)。例如6、8都是醜數,但14不是,因為它包含因子7。習慣上我們把1當做是第一個醜數。求按從小到大的順序的第N個醜數。 輸入:輸入包括一個整數N(1<=N<=1500)。 輸

OJ題目1047素數判定

時間限制:1 秒 記憶體限制:32 兆 特殊判題:否 題目描述: 給定一個數n,要求判斷其是否為素數(0,1,負數都是非素數)。 輸入: 測試資料有多組,每組輸入一個數n。 輸出: 對於每組輸入,若是素數則輸出yes,否則輸入no。 樣例輸入: 13 樣例輸出: yes #include

oj 題目1008最短路徑問題

這道題告訴我們 INT_MAX, 慎用,dijkstra 有時加溢位了,你都不知道 #include <cstdio> //#include <climits> #include <algorithm> using namespace

OJ 題目1008最短路徑問題 (Dijstra 演算法)

題目描述: 給你n個點,m條無向邊,每條邊都有長度d和花費p,給你起點s終點t,要求輸出起點到終點的最短距離及其花費,如果最短距離有多條路線,則輸出花費最少的。 輸入: 輸入n,m,點的編號是1~n,然後是m行,每行4個數 a,b,d,p,表示a和b之間有一條邊,且其長度為

OJ 題目1126列印極值點下標

 一.題目描述: 在一個整數陣列上,對於下標為i的整數,如果它大於所有它相鄰的整數,  或者小於所有它相鄰的整數,則稱為該整數為一個極值點,極值點的下標就是i。 輸入: 每個案例的輸入如下: 有2×n+1行輸入:第一行是要處理的陣列的個數n;  對其餘2×n行,第一

OJ-題目1163素數

題目描述: 輸入一個整數n(2<=n<=10000),要求輸出所有從1到這個整數之間(不包括1和這個整數)個位為1的素數,如果沒有則輸出-1。 輸入: 輸入有多組資料。 每組一行,輸入n。 輸出: 輸出所有從1到這個整數之間(不包

OJ題目1067n的階乘

題目描述: 輸入一個整數n,輸出n的階乘 輸入: 一個整數n(1<=n<=20) 輸出: n的階乘 樣例輸入: 3 樣例輸出: 6 #include <stdio.h> #include <string.h> #include <stdlib.h>