打印二叉树某一层的节点
按层非递归遍历二叉树是一道常见的题目,编程之美上有一个打印出二叉树某一层的节点的问题,稍稍有意思。
在编程之美上,提到了两种解法:
(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); } }
里面用到的队列是自己写的,也当作一个小练习。
完整测试代码:
queue.h
#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__ */
btree.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__ */
btree.cc
#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); } }
main.cc
#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; }