二叉树的层次遍历-1

1.二叉树层次遍历的原理

算法思想:
  利用队列实现的,因为层次遍历的序列正好符合队列的特性,先进先出,所以用队列这个工具实现二叉树的层次遍历
  但pay attention to 这里我用的是循环队列,因我害怕队列溢出,导致内存泄漏的不规范行

2.代码如下

#include<iostream>
#include<cstdio>
#include<cstdlib>
#define MaxSize 50
using namespace std;
typedef char ElemType;
//树结点定义
typedef struct node{
    ElemType data;
    struct node* lchild,*rchild;
}BiTNode,*BiTree;

//采用循环队列定义
typedef struct{
    BiTree value[MaxSize];
    int front,rear;
}Qunue;
//初始化循环队列
void InitQunue(Qunue &Q)
{
    Q.front=Q.rear=0;
}
//入队操作
bool EnQunue(Qunue &Q,BiTree x)
{
    //入队判断队列是否满了
    if((Q.rear+1)%MaxSize==Q.front)
    {
        printf("循环队列已经满了,无法入队了!
");
        return false;
    }
    else{
        Q.value[Q.rear]=x;
        Q.rear=(Q.rear+1)%MaxSize;
        return true;
    }
}
//出队操作
bool DeQunue(Qunue &Q,BiTree &x)
{
    //出队操作判断队列是否为空
    if(Q.rear==Q.front)
    {
        printf("队列为空,无法出队!
");
        return false;
    }
    else{
        x=Q.value[Q.front];
        Q.front=(Q.front+1)%MaxSize;
        return false;
    }
}
//判断队列是否为空
bool EmpytQunue(Qunue Q)
{
    if(Q.rear==Q.front)
    {
        return true;
    }
    else{
        return false;
    }
}

//初始化一个空的二叉树
void InitBiTree(BiTree &tree)
{
    // tree存储NULL,表示没有二叉树
    tree=NULL;
}
//先序递归创建二叉树  #表示空结点
//eg: 12#### 表示的是根为1,左孩子为2
void CreateBitree(BiTree &T)
{
    char ch;
    if((ch=getchar())=='#')
        T=NULL;
    else
    {
        T=(BiTNode*)malloc(sizeof(BiTNode));
        T->data=ch;
        CreateBitree(T->lchild);
        CreateBitree(T->rchild);
    }
}

//层次遍历
bool LevelOrder(BiTree &tree)
{
    Qunue Q;  初始化一个循环队列
    InitQunue(Q);
    BiTree p=tree,q,r;   //保护
    if (p)
    {
        EnQunue(Q,p);  //先把根节点入队,为了构造循环结束的条件,队列为空
    }
    else{
        cout<<"二叉树为空,无法进行层次遍历!"<<endl;
        return false;
    };
    while(!EmpytQunue(Q))
    {
        if(p->lchild)   //左孩子结点存在,入队
        {
            EnQunue(Q,p->lchild);
        }
        if (p->rchild)  //右孩子节点存在入队
        {
            EnQunue(Q,p->rchild);   //当处理完下一行时,上一行的左结点出队包括根节点(其实也可一全进入队列里最后在统一出队,都可以)
            DeQunue(Q,p);  //出队列
            printf("%c",p->data);  //输出结点值
            if(p->lchild==NULL)  //if-else 为了,让p指向下一行的左结点或者右结点(因为右结点可能不存在)
                p=p->rchild;
            else
                p=p->lchild;
        }
        if(p->lchild==NULL&&p->rchild==NULL)   //当p的左右都为空时,结束层次遍历
            while (!EmpytQunue(Q))
            {
                DeQunue(Q,p);
                printf("%c",p->data);   //输出队列中保存的所有结点数据
            }
    }
    return true;
}

int main()
{
    BiTree tree;    //创建一个二叉树结点指针
    InitBiTree(tree); //初始化一个空二叉树
    CreateBitree(tree);  //先序递归创建一个二叉树
  
    LevelOrder(tree);  //层次遍历结果序列


    return 0;
}
第一种实现
#include<iostream>
#include<cstdio>
#include<cstdlib>
#define MaxSize 50
using namespace std;
typedef char ElemType;
//树结点定义
typedef struct node{
    ElemType data;
    struct node* lchild,*rchild;
}BiTNode,*BiTree;

//采用循环队列定义
typedef struct{
    BiTree value[MaxSize];
    int front,rear;
}Qunue;
//初始化循环队列
void InitQunue(Qunue &Q)
{
    Q.front=Q.rear=0;
}
//入队操作
bool EnQunue(Qunue &Q,BiTree x)
{
    //入队判断队列是否满了
    if((Q.rear+1)%MaxSize==Q.front)
    {
        printf("循环队列已经满了,无法入队了!
");
        return false;
    }
    else{
        Q.value[Q.rear]=x;
        Q.rear=(Q.rear+1)%MaxSize;
        return true;
    }
}
//出队操作
bool DeQunue(Qunue &Q,BiTree &x)
{
    //出队操作判断队列是否为空
    if(Q.rear==Q.front)
    {
        printf("队列为空,无法出队!
");
        return false;
    }
    else{
        x=Q.value[Q.front];
        Q.front=(Q.front+1)%MaxSize;
        return false;
    }
}
//判断队列是否为空
bool EmpytQunue(Qunue Q)
{
    if(Q.rear==Q.front)
    {
        return true;
    }
    else{
        return false;
    }
}

//初始化一个空的二叉树
void InitBiTree(BiTree &tree)
{
    // tree存储NULL,表示没有二叉树
    tree=NULL;
}
//先序递归创建二叉树  #表示空结点
void CreateBitree(BiTree &T)
{
    char ch;
    if((ch=getchar())=='#')
        T=NULL;
    else
    {
        T=(BiTNode*)malloc(sizeof(BiTNode));
        T->data=ch;
        CreateBitree(T->lchild);
        CreateBitree(T->rchild);
    }
}

//层次遍历
bool LevelOrder(BiTree &tree)
{
    Qunue Q;
    InitQunue(Q);
    BiTree p=tree,q,r;   //保护
    if (p)
    {
        EnQunue(Q,p);  //先把跟入队,为了判断
    }
    else{
        cout<<"二叉树为空,无法进行层次遍历!"<<endl;
        return false;
    };
    while(!EmpytQunue(Q))
    {
        if(p->lchild)
        {
            q=p->lchild;
            EnQunue(Q,p->lchild);
        }
        if (p->rchild)
        {
            EnQunue(Q,p->rchild);
            DeQunue(Q,p);  //出队列  第二种逻辑控制,一次出对两个,正好把p赋值成左结点了
            printf("%c",p->data);
            DeQunue(Q,p);
            printf("%c",p->data);
//            if(p->lchild==NULL)
//                p=p->rchild;
//            else
//                p=p->lchild;
        }
        if(p->lchild==NULL&&p->rchild==NULL)   //当p的左右都为空时,结束层次遍历
            while (!EmpytQunue(Q))
            {
                DeQunue(Q,p);
                printf("%c",p->data);
            }
    }
    return true;
}

int main()
{
    BiTree tree;
    InitBiTree(tree);
    CreateBitree(tree);
    LevelOrder(tree);


    return 0;
}
第二种实现
#include<iostream>
#include<cstdio>
#include<cstdlib>
#define MaxSize 50
using namespace std;
typedef char ElemType;
//树结点定义
typedef struct node{
    ElemType data;
    struct node* lchild,*rchild;
}BiTNode,*BiTree;

//采用循环队列定义
typedef struct{
    BiTree value[MaxSize];
    int front,rear;
}Qunue;
//初始化循环队列
void InitQunue(Qunue &Q)
{
    Q.front=Q.rear=0;
}
//入队操作
bool EnQunue(Qunue &Q,BiTree x)
{
    //入队判断队列是否满了
    if((Q.rear+1)%MaxSize==Q.front)
    {
        printf("循环队列已经满了,无法入队了!
");
        return false;
    }
    else{
        Q.value[Q.rear]=x;
        Q.rear=(Q.rear+1)%MaxSize;
        return true;
    }
}
//出队操作
bool DeQunue(Qunue &Q,BiTree &x)
{
    //出队操作判断队列是否为空
    if(Q.rear==Q.front)
    {
        printf("队列为空,无法出队!
");
        return false;
    }
    else{
        x=Q.value[Q.front];
        Q.front=(Q.front+1)%MaxSize;
        return false;
    }
}
//判断队列是否为空
bool EmpytQunue(Qunue Q)
{
    if(Q.rear==Q.front)
    {
        return true;
    }
    else{
        return false;
    }
}

//初始化一个空的二叉树
void InitBiTree(BiTree &tree)
{
    // tree存储NULL,表示没有二叉树
    tree=NULL;
}
//先序递归创建二叉树  #表示空结点
void CreateBitree(BiTree &T)
{
    char ch;
    if((ch=getchar())=='#')
        T=NULL;
    else
    {
        T=(BiTNode*)malloc(sizeof(BiTNode));
        T->data=ch;
        CreateBitree(T->lchild);
        CreateBitree(T->rchild);
    }
}

//层次遍历
bool LevelOrder(BiTree &tree)
{
    Qunue Q;
    InitQunue(Q);
    BiTree p=tree;   //保护
    if (p)
    {
        EnQunue(Q,p);  //先把跟入队,为了判断
    }
    else{
        cout<<"二叉树为空,无法进行层次遍历!"<<endl;
        return false;
    };
    while(!EmpytQunue(Q))
    {
        DeQunue(Q,p);
        printf("%c",p->data);  //这里放置访问结点的各种操作  这里用的只是输出
        if(p->lchild)
        {
            EnQunue(Q,p->lchild);
        }
        if (p->rchild)
        {
            EnQunue(Q,p->rchild);
        }
    }
    return true;
}

int main()
{
    BiTree tree;
    InitBiTree(tree);
    CreateBitree(tree);
    LevelOrder(tree);


    return 0;
}
第三种实现

本质都是一样的,只不过改了改逻辑.

3.要变通,printf语句那里可以替换成你想要的任何语句

4.结果测试  

原文地址:https://www.cnblogs.com/nanfengnan/p/14544994.html