Fork me on GitHub

打印二叉树某一层的节点

按层非递归遍历二叉树是一道常见的题目,编程之美上有一个打印出二叉树某一层的节点的问题,稍稍有意思。

在编程之美上,提到了两种解法:

(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;
}

 

posted @ 2013-02-25 00:43  _Lei  阅读(5087)  评论(1编辑  收藏  举报