数据结构 C 代码 x: 二叉树层次遍历的队列实现

本贴为《数据结构》课程服务.

1. 主要内容

  1. 二叉树的层次遍历.
  2. 使用队列

2. 代码

2.1 李毛毛

说明:

  1. 几种遍历方式集成在一个程序里, 我就偷懒没把它们分开.
  2. 队列应该叫做 enqueue, dequeue, 栈的操作才是 push, pop.
// 李毛毛

#include<iostream>
#include<cstdlib>
#include<stack>
#include<queue>
using namespace std;

typedef struct BinTreeNode
{
    char data;
    struct BinTreeNode *leftChild;
    struct BinTreeNode *rightChild;
}*myTree;

//函数申明
void CreateBinTree(myTree tree);

//二叉树递归遍历
void preorderTraversal(myTree tree); //(中左右)
void inorderTraversal(myTree tree);  //(左中右)
void orderTraversal(myTree tree);    //(右中左)

//二叉树的栈(非递归)遍历
void PreOrder_NoRecurve1(myTree p); //先序遍历
void InOrder_NoRecurve(myTree p);   //中序遍历
void PostOrder_NoRecurve(myTree p); //后序遍历

//二叉树的队列(非递归)遍历
void LevelOrder(myTree p);

int main()
{
    cout<<"请输入你要创建的二叉树(以#结束):";
    myTree root = NULL;
    CreateBinTree(root);
    return 0;
}

//使用广义表创建二叉树函数,这里以“字符”创建二叉树,以'#'字符代表结束
void CreateBinTree(myTree root)
{
    stack<myTree> s;
    int k;           //k是处理左、右子树的标记
    myTree p,t;      //p用来记住当前创建的节点,t用来记住栈顶的元素
    char ch;
    cin>>ch;

    while(ch != '#')
    {
        switch(ch)
        {
        case '(':       //对(做处理
            s.push(p);
            k=1;
            break;

        case ')':      //对)做处理
            s.pop();
            break;

        case ',':      //对,做处理
            k=2;
            break;

        default:
            p = (myTree)malloc(sizeof(BinTreeNode));    //构造一个结点
            p->leftChild = NULL;
            p->rightChild = NULL;
            if (root == NULL)    //如果头节点是空
            {
                root = p;
                p->data = ch;
            }
            else if (k == 1)    //链入*t的左孩子
            {
                t = s.top();
                t->leftChild = p;
                p->data = ch;
            }
            else    //链入*t的右孩子
            {
                t = s.top();
                t->rightChild = p;
                p->data = ch;
            }
        }
        cin>>ch;
    }
    cout<<endl<<"采用递归遍历二叉树"<<endl;

    cout<<"使用中左右输出:";
    preorderTraversal(root);
    cout<<endl;
    cout<<"使用左中右输出:";
    inorderTraversal(root);
    cout<<endl;
    cout<<"使用左右中输出:";
    orderTraversal(root);

    cout<<endl<<endl<<"采用栈遍历二叉树:"<<endl;

    cout<<"使用先序输出:";
    PreOrder_NoRecurve1(root);
    cout<<endl;
    cout<<"使用中序输出: ";
    InOrder_NoRecurve(root);
    cout<<endl;
    cout<<"使用后序输出:";
    PostOrder_NoRecurve(root);
    cout<<endl;

    cout<<endl<<"采用层次遍历(队列)二叉树:" <<endl;
    LevelOrder(root);
    cout<<endl;

}

/*myTree constructABinaryTree() {                        //创建一个二叉树
	myTree root = (myTree)malloc(sizeof(BinTreeNode));
	root->data = 5;
	root->leftChild = NULL;
	root->leftChild = NULL;
	myTree leftChild = (myTree)malloc(sizeof(BinTreeNode));
	leftChild->data = 7;
	leftChild->leftChild = NULL;
	leftChild->rightChild = NULL;
	root->leftChild = leftChild;
	myTree rightChild = (myTree)malloc(sizeof(BinTreeNode));
	rightChild->data = 6;
	rightChild->leftChild = NULL;
	rightChild->rightChild = NULL;
	root->rightChild = rightChild;
	myTree twoLeftChild = (myTree)malloc(sizeof(BinTreeNode));
	twoLeftChild->data = 4;
	twoLeftChild->leftChild = NULL;
	twoLeftChild->rightChild = NULL;
	leftChild->leftChild = twoLeftChild;
	myTree leftRightChild = (myTree)malloc(sizeof(BinTreeNode));
	leftRightChild->data = 3;
	leftRightChild->leftChild = NULL;
	leftRightChild->rightChild = NULL;
    leftChild->rightChild = leftRightChild;
	return root;
}*/

void preorderTraversal(myTree tree)
{
    cout << tree->data << "  ";
    if (tree->leftChild != NULL) preorderTraversal(tree->leftChild);
    if (tree->rightChild != NULL)preorderTraversal(tree->rightChild); //中左右
}

void inorderTraversal(myTree tree)
{

    if (tree->leftChild != NULL) inorderTraversal(tree->leftChild);   //左中右
    cout << tree->data << "  ";
    if (tree->rightChild != NULL)inorderTraversal(tree->rightChild);
}

void orderTraversal(myTree tree)                                       //左右中、
{

    if (tree->leftChild != NULL) orderTraversal(tree->leftChild);
    if (tree->rightChild != NULL)orderTraversal(tree->rightChild);
    cout << tree->data<<"  ";
}

void PreOrder_NoRecurve1(myTree p)     //先序遍历
{
    stack<myTree> s;
    s.push(NULL); /*最先push一个NULL,到最后一个结点没有左右子树时,
	栈里只有一个NULL了,令指针p指向这个NULL,再判断就会结束循环*/

    while (p!=NULL)
    {
        cout << p->data << "  ";
        if(p->rightChild!=NULL)    //预留右子树指针在栈中
        {
            s.push(p->rightChild);
        }

        if (p->leftChild!=NULL)    //进左子树
        {
            p = p->leftChild;
        }
        else    //左子树为空
        {
            p = s.top();
            s.pop();
        }
    }

}

void InOrder_NoRecurve(myTree p)       //中序遍历
{
    stack<myTree> s;
    do
    {
        while (p!=NULL)
        {
            s.push(p);
            p = p->leftChild;
        }
        if (!s.empty())
        {
            p = s.top();
            s.pop();
            cout << p->data << "  ";
            p = p->rightChild;
        }
    }
    while (p!=NULL||!s.empty());

}

void PostOrder_NoRecurve(myTree p)    //后序遍历
{
    if (p == NULL)
        return ;
    stack<myTree> s;
    s.push(p);
    myTree lastPop = NULL;
    while (!s.empty())
    {
        while (s.top()->leftChild != NULL)
            s.push(s.top()->leftChild);
        while (!s.empty())
        {
            //右叶子结点 || 没有右结点
            if (lastPop == s.top()->rightChild || s.top()->rightChild == NULL)
            {
                cout << s.top()->data << "  ";
                lastPop = s.top();
                s.pop();
            }
            else if (s.top()->rightChild != NULL)
            {
                s.push(s.top()->rightChild);
                break;
            }
        }
    }

}

void LevelOrder(myTree p)      //队列层次遍历
{
    queue<myTree> Q;
    Q.push(p);    //根节点进队
    myTree t;
    while (!Q.empty())
    {
        t = Q.front();    //t先记住队头,再将队头出队
        Q.pop();
        cout << t->data << "  ";    //访问队头元素的数据

        if (t->leftChild != NULL)
        {
            Q.push(t->leftChild);
        }

        if (t->rightChild != NULL)
        {
            Q.push(t->rightChild);
        }
    }
}

2.2 付乐兵

助教辜果推荐.

//付乐兵,202031061023,计算机类1班
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#define MAXSIZE 100
#define	TRUE 1
#define FALSE 0
#define YES 1
#define NO 0
#define ERROR 0
#define SUCCESS 1
typedef int QElemType;
typedef int Status;
typedef char TElemType;
typedef char ElemType;
typedef struct BiTNode
{
    TElemType data;          //结点元素
    struct BiTNode *lchild;    //左孩子指针
    struct BiTNode *rchild;    //右孩子指针
} BiTNode,*BiTree;
//-----------------------//
typedef struct StackNode
{
    BiTree Stack_data;		//栈的数据域存放树的结点
    struct StackNode *next;
} StackNode,*LinkStack;
//-----------------------//
typedef struct QNode
{
    BiTree QT;		 	//数据域存放树的结点
    struct QNode *next;
} QNode,*QueuePtr;
typedef struct
{
    QueuePtr front;		//队头指针
    QueuePtr rear;		//队尾指针
} LinkQueue;
//----------------------//
LinkStack InitStack(LinkStack &S);	//初始化
bool StackEmpty(LinkStack S);		//判空
void Push(LinkStack &S,BiTree e);	//入栈
BiTree Pop(LinkStack S);			//出栈
//-----------------------------------//
void InitBiTree(BiTree &T);
//构造空二叉树T
BiTree CreateBiTree(BiTree &T);
//创建二叉树
Status BiTreeEmpty(BiTree T);
//判断二叉树是否为空
BiTree frontNode(BiTree T);
//后序时前驱节点
void PreOrderTraverse(BiTree T);
//非递归算法先序遍历二叉树
void InOrderTraverse(BiTree T);
//非递归算法中序遍历二叉树
void PostOrderTraverse(BiTree T);
//非递归算法后序遍历二叉树
void LevelOrderTraverse(BiTree T);
//层序遍历二叉树

//---------------------//
void InitQueue(LinkQueue &Q);
//构造一个空队列Q
void EnQueue(LinkQueue &Q,BiTree T);
//入队
BiTree DeQueue(LinkQueue &Q);
//出队
//---------------------//

int main()
{
    BiTree T;
    InitBiTree(T);
    printf("测试样例:1,2,4,#,#,5,#,#,3,6,#,#,7,#,#\n");
    printf("请输入头结点:");
    CreateBiTree(T);
    printf("前序遍历\n");
    PreOrderTraverse(T);
    printf("\n");
    printf("中序遍历\n");
    InOrderTraverse(T);
    printf("\n");
    printf("后序遍历\n");
    PostOrderTraverse(T);
    printf("\n");
    printf("队列实现层次遍历\n");
    LevelOrderTraverse(T);
}
LinkStack InitStack(LinkStack &S)
{
    S=(StackNode*)malloc(sizeof(StackNode*));
    S->next=NULL;
    return S;
}
void Push(LinkStack &S,BiTree e)
{
    if(e)	//若树不为空
    {
        StackNode *p=(StackNode *)malloc(sizeof(StackNode));
        p->Stack_data=e;
        p->next=S->next;
        S->next=p;
    }
}
bool StackEmpty(LinkStack S)
{
    if(S==NULL)
        return false;
    else
        return S->next==NULL;
}
BiTree Pop(LinkStack S)
{
    if(StackEmpty(S))
    {
        printf("Stack is empty!\n");
        return NULL;
    }
    BiTree mid = S->next->Stack_data;
    LinkStack p = S->next;
    S->next = p->next;
    free(p);

    return mid;
}
//----------------------------------------//
void InitBiTree(BiTree &T)//构造空二叉树T
{
    T = NULL;
    printf("初始化成功!\n");
    return ;
}

BiTree CreateBiTree(BiTree &T)//创建二叉树
{
    TElemType ch;
    scanf("%c",&ch);
    getchar();			//吃掉回车键
    if(ch == '#')		//若输入#表示该位置为NULL
        return  NULL;
    T = (BiTree)malloc(sizeof(BiTNode));	//分配树结点
    if(!T)
        printf("失败\n");
    T->data = ch;

    printf("请输入%c的左子树:",T->data);
    T->lchild=	CreateBiTree(T->lchild);

    printf("请输入%c的右子树:", T->data);
    T->rchild = CreateBiTree(T->rchild);

    return T;
}

Status BiTreeEmpty(BiTree T)//判断二叉树是否为空
{
    if(T==NULL)
        return TRUE;
    else
        return FALSE;
}

BiTree frontNode(BiTree T)
{
    if (T->rchild)
        return T->rchild;
    return T->lchild;
}

void PreOrderTraverse(BiTree T)//栈实现先序遍历二叉树
{
    LinkStack stackTop;
    InitStack(stackTop);
    while(T)
    {
        //从根开始,往左遍历到头
        while(T)
        {
            printf("%c ", T->data);    	//遇到结点就输出
            Push(stackTop,T->rchild);   //将该节点的右节点进行压栈,压栈操作会自己判断数据是否有效
            T = T->lchild;    			//依次输出左节点
        }

        if (!StackEmpty(stackTop))		//若栈不为空
            T = Pop(stackTop);			//最近的右结点出栈
    }
}

void InOrderTraverse(BiTree T)	//堆栈实现中序遍历
{
    LinkStack stackTop;
    InitStack(stackTop);

    while(T || !StackEmpty(stackTop))
    {
        while(T)
        {
            Push(stackTop, T);
            T = T->lchild;
        }
        if (!StackEmpty(stackTop))
        {
            T = Pop(stackTop);
            printf("%c ", T->data);
            T = T->rchild;
        }
    }
}

void PostOrderTraverse(BiTree T)//栈后序遍历二叉树
{
    LinkStack stackTop;
    InitStack(stackTop);
    BiTree last = NULL;

    while(T || !StackEmpty(stackTop))
    {
        while(T)		//遍历左子树压栈
        {
            Push(stackTop, T);
            T = T->lchild;
        }
        if (!StackEmpty(stackTop))
        {
            BiTree judge = stackTop->next->Stack_data->rchild;
            if (judge)
            {
                T = judge;    //判断是否有右子节点,有就把它当做子树的根节点先行遍历
            }
            else
            {
                last = Pop(stackTop);    //如果没有右子节点,那说明为叶子节点,出栈
                printf("%c ", last->data);
                while(!StackEmpty(stackTop) && last == frontNode(stackTop->next->Stack_data))
                {
                    //当弹出一个叶子节点之后,需要将前驱节点已经弹出的全部都弹出
                    last = Pop(stackTop);
                    printf("%c ", last->data);
                }
                T = NULL;    //弹出前面的节点以后,说明该子树已经遍历完,不再进行重复遍历
            }
        }
    }
}

void InitQueue(LinkQueue &Q)
{
    Q.front=Q.rear=(QueuePtr)malloc(sizeof(QNode));//此处不用->要用.
    if(!Q.front) exit(OVERFLOW);
    Q.front->next=NULL;
}

void EnQueue(LinkQueue &Q,BiTree T)		//入队
{
    QueuePtr p = (QueuePtr)malloc(sizeof(QNode));
    if(p == NULL)
        exit(0);
    else
    {
        p->QT = T;
        p->next = NULL;
        Q.rear->next = p;
        Q.rear = p;
        return ;
    }
}

BiTree DeQueue(LinkQueue &Q)	//出队
{
    QueuePtr p = Q.front->next;
    if(Q.front == Q.rear)
        return NULL;
    Q.front->next = p->next;
    if(Q.rear == p)
        Q.rear = Q.front;
    return p->QT;
}

void LevelOrderTraverse(BiTree T)//层序遍历二叉树
{
    BiTree t = NULL;
    LinkQueue Q;
    InitQueue(Q);
    if(T != NULL)
        EnQueue(Q,T);                      //若树不空,让根节点入队
    else
        return;
    while(Q.front != Q.rear)                 //队列不空
    {
        t = DeQueue(Q);                    	//元素出队
        printf("%c ",t->data);
        if(t->lchild != NULL)               //判断子左子树是否为空
            EnQueue(Q,t->lchild);           //不空则让它入队
        if(t->rchild != NULL)               //判断子右子树是否为空
            EnQueue(Q,t->rchild);          	//不空则让它入队
    }
    printf("\n");
    return;
}

3. 建议与意见

来拍砖吧!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值