按層非遞歸遍歷二叉樹是一道常見的題目,編程之美上有一個打印出二叉樹某一層的節點的問題,稍稍有意思。
在編程之美上,提到了兩種解法:
(1)一種是遞歸解法
void TransLevel(Node* root,int level) { if(root == NULL) return ; else { if(level == 1) printf("%d ",root->data); else { TransLevel(root->left,level-1); TransLevel(root->right,level-1); } } }
(2)另一種則是利用隊列的非遞歸解法
如果只是簡單的按層遍歷的話,可以用一個隊列,先將上層節點入隊,節點出隊的時候將其孩子節點入隊,這樣就可以達到按層入隊出隊的效果。
要打印出某一層,可以在出隊的時候一層一層地出,同時計算出隊的次數,就可以判斷出當前是哪一層,下面是我的代碼:
void TransLevel2(Node* root,int level) { if(root == NULL) return ; else { int count_levels,count_nodes,level_nodes; Node* tmp; Queue<Node*> queue; queue.EnQueue(root); count_levels=1; while(!queue.IsEmpty()) { //如果已經是要打印的層 if(count_levels == level) break; count_nodes = 0; //計算上一層的節點數 level_nodes = queue.Size(); //每一次將一個節點出隊,直至上一層所有節點出隊 //同時將下一層的節點入隊 while(count_nodes < level_nodes) { tmp = queue.DeQueue(); if(tmp->left != NULL) queue.EnQueue(tmp->left); if(tmp->right != NULL) queue.EnQueue(tmp->right); count_nodes++; } count_levels++; } //隊列中剩下的元素即為要打印的節點 PrintQueue(queue); } }
里面用到的隊列是自己寫的,也當作一個小練習。
完整測試代碼:

#ifndef __QUEUE_H__ #define __QUEUE_H__ #include <memory.h> #define MAX_SIZE 100 template <typename T> class Queue { public: Queue(); bool EnQueue(const T element); T DeQueue(); bool IsEmpty() const; bool IsFull() const; int Size() const; private: T queue[MAX_SIZE]; int front; int rear; }; template<typename T> Queue<T>::Queue() :front(0),rear(0) { memset(queue,0,sizeof(queue)); } template<typename T> bool Queue<T>::EnQueue(const T element) { if(IsFull()) return false; else { rear = (rear+1)%MAX_SIZE; queue[rear] = element; return true; } } template<typename T> T Queue<T>::DeQueue() { if(IsEmpty()) return 0; else { front = (front+1)%MAX_SIZE; return queue[front]; } } template<typename T> bool Queue<T>::IsEmpty() const { return front == rear; } template<typename T> bool Queue<T>::IsFull() const { return (rear+1) % MAX_SIZE == front; } template<typename T> int Queue<T>::Size() const { return rear-front; } #endif /* __QUEUE_H__ */

#ifndef __BTREE_H__ #define __BTREE_H__ struct Node { struct Node* left; struct Node* right; int data; }; void BuildTree(int array[],int n,struct Node** root,int i); void DestroyTree(struct Node* root); void PrintTree(Node* root); int GetDepth(Node* root); void TransLevel(Node* root,int level); void TransLevel2(Node* root,int level); #endif /* __BTREE_H__ */

#include "btree.h" #include <memory.h> #include <stdlib.h> #include <stdio.h> #include "queue.h" void BuildTree(int array[],int n,Node** root,int i) { if(i<n) { *root = (Node*)malloc(sizeof(Node)); (*root)->data = array[i]; BuildTree(array,n,&(*root)->left,i*2+1); BuildTree(array,n,&(*root)->right,(i+1)*2); } } void DestroyTree(Node* root) { if(root!=NULL) { DestroyTree(root->left); DestroyTree(root->right); free(root); } } void PrintTree(Node* root) { if(root!=NULL) { printf("%d ",root->data); PrintTree(root->left); PrintTree(root->right); } } int GetDepth(Node* root) { if(root == NULL) return 0; else { int left_depth=GetDepth(root->left); int right_depth=GetDepth(root->right); return left_depth>right_depth ? left_depth+1 : right_depth+1; } } void TransLevel(Node* root,int level) { if(root == NULL) return ; else { if(level == 1) printf("%d ",root->data); else { TransLevel(root->left,level-1); TransLevel(root->right,level-1); } } } static void PrintQueue(Queue<Node*>& queue) { Node* node = NULL; while(!queue.IsEmpty()) { node = queue.DeQueue(); printf("%d ",node->data); } } void TransLevel2(Node* root,int level) { if(root == NULL) return ; else { int count_levels,count_nodes,level_nodes; Node* tmp; Queue<Node*> queue; queue.EnQueue(root); count_levels=1; while(!queue.IsEmpty()) { if(count_levels == level) break; count_nodes = 0; level_nodes = queue.Size(); while(count_nodes < level_nodes) { tmp = queue.DeQueue(); if(tmp->left != NULL) queue.EnQueue(tmp->left); if(tmp->right != NULL) queue.EnQueue(tmp->right); count_nodes++; } count_levels++; } PrintQueue(queue); } }

#include <stdio.h> #include "btree.h" int main() { int array[]={1,2,3,4,5,6,7,8,9,10}; Node* root=NULL; BuildTree(array,10,&root,0); int depth = GetDepth(root); /* 使用遞歸方法打印二叉樹的某一層 */ for(int i=1;i<=depth;i++) TransLevel(root,i); printf("\n"); /* 使用非遞歸方法打印二叉樹的某一層 */ for(int i=1;i<=depth;i++) TransLevel2(root,i); printf("\n"); DestroyTree(root); return 0; }