二叉树的遍历--递归、非递归、按层次遍历

二叉树的概念

二叉树是一种树形结构,其特点是每个结点至多只有两棵子树( 即二叉树中不存在度大于2的结点),并且二叉树的子树有左右之分,其次序不能任意颠倒

二叉树的存储

顺序存储

即按照从上到下的顺序逐层存放,遇到为空的结点用‘0’表示。

链式存储

采用链式存储结构,用左指针域(lchild)存放结点的左孩子,用右指针域(rchild)存放右孩子

二叉树的创建

这是最常见的创建二叉树的方法。采用递归的形式,遇到空结点输入‘^’表示空。如果用户输入判断非空,则创建该结点,为它分配空间并且赋值。随后递归调用自身,以左节点为根继续判断

typedef char DataType;

typedef struct Node
{
    DataType data;
    struct Node * Lchild;
    struct Node * Rchild;
}BiTNode,*BiTree;


BiTree CreatBiTree()//用扩展先序遍历序列创建二叉链表
{
    BiTree bt;
    char ch;
    ch=getchar();
    if(ch=='^')
        return NULL;
    bt=(BiTree )malloc(sizeof(BiTNode));
    bt->data=ch;
    bt->Lchild = CreatBiTree();
    bt->Rchild = CreatBiTree();
    return bt;
}

 比如用户输入:621^^43^^^8^^,其结果如图所示:

                                                   

二叉树的遍历

二叉树的遍历有很多方法,例如递归的先序、中序、后序遍历,非递归遍历,按层次遍历等。

递归遍历

先序遍历

操作过程如下:
若二叉树为空,则什么也不做,否则,
1)访问根结点;
2)先序遍历左子树;
3)先序遍历右子树

中序遍历

操作过程如下:
若二叉树为空,则什么也不做,否则,
1)中序遍历左子树;
2)访问根结点;
3)中序遍历右子树。

后序遍历

操作过程如下:
若二叉树为空,则什么也不做,否则,
1)后序遍历左子树;
2)后序遍历右子树;
3)访问根结点。

例如此二叉树:

                                                     

先序遍历的结果:6 2 1 4 3 8

中序遍历的结果:1 2 3 4 6 8

后序遍历的结果:1 3 4 2 8 6

代码实现

此代码是后序遍历代码,先序、中序只不过将printf函数调换顺序就可以实现

//后序遍历
void  HindOrderLayer (BiTree bt){
    if(bt==NULL){
        return;
    }
    HindOrderLayer(bt->Lchild);
    HindOrderLayer(bt->Rchild);
    printf("%d ",bt->data);
}

非递归遍历

任何能以递归形式处理的问题都能以非递归的栈来处理,二叉树的遍历也不例外。

此代码使用栈的思想,进行非递归的先序遍历。先判断此树是否为空,如果为空直接返回就行。

先将根节点入栈

stack[++top] = root;

 然后在while循环中,依次取出栈顶元素并打印,然后将该结点的右孩子和左孩子依次进栈,因为我们进行的是先序遍历,根据栈的后进先出规则,左孩子后进的,则会先被弹出栈

当栈为空的时候则遍历结束。

代码实现:

void preorderTraversal(BiTree root) {
    if (root == NULL) {
        return;
    }

    BiTree stack[1000];
    int top = -1;

    stack[++top] = root;//入栈

    while (top >= 0) {
        BiTree node = stack[top--];//出栈

        printf("%d ", node->data);

        if (node->Rchild) {
            stack[++top] = node->Rchild;
        } 

        if (node->Lchild) {
            stack[++top] = node->Lchild;
        }
    }
}

 按层次遍历

按层次遍历即从上到下从左到右依次遍历。此方法要用到的是队列的操作。

                                                   

还是以这个树为例:

先将根结点入队,此时队列中有‘6’;

然后将根结点出队打印,并将根结点的左孩子右孩子入队,此时队列中有‘2’,‘8’;

然后继续将‘2’出队打印,并将‘2’的左孩子右孩子入队,此时队列中有‘8’,‘1’,‘4’;

就这样继续操作直到队列为空,此时打印出来的就是按层次遍历的结果。

代码实现

void levelOrderTraversal(BiTree root) {
    if (root == NULL) {
        return;
    }

    struct Node* queue[1000];
    int front = 0;
    int rear = 0;

    queue[rear++] = root;

    while (front < rear) {
        struct Node* node = queue[front++];
        printf("%d ", node->data);

        if (node->Lchild) {
            queue[rear++] = node->Lchild;
        }

        if (node->Rchild) {
            queue[rear++] = node->Rchild;
        }
    }
}

完整代码

#include<stdio.h>
#include<stdlib.h>
typedef char DataType;

typedef struct Node
{
    DataType data;
    struct Node * Lchild;
    struct Node * Rchild;
}BiTNode,*BiTree;
void preorderTraversal(BiTree root);
void  HindOrderLayer (BiTree bt);
BiTree CreatBiTree();//用扩展先序遍历序列创建二叉链表
void levelOrderTraversal(BiTree root); 
int main()
{
    BiTree root;
    root=CreatBiTree();
    printf("后序遍历\n");
    HindOrderLayer (root);
    printf("\n非递归遍历\n");
    preorderTraversal(root);
    printf("\n按层次遍历遍历\n");
    levelOrderTraversal(root);
}

BiTree CreatBiTree()//用扩展先序遍历序列创建二叉链表
{
    BiTree bt;
    char ch;
    ch=getchar();
    if(ch=='^')
        return NULL;
    bt=(BiTree )malloc(sizeof(BiTNode));
    bt->data=ch;
    bt->Lchild = CreatBiTree();
    bt->Rchild = CreatBiTree();
    return bt;
}


void levelOrderTraversal(BiTree root) {
    if (root == NULL) {
        return;
    }

    struct Node* queue[1000];
    int front = 0;
    int rear = 0;

    queue[rear++] = root;

    while (front < rear) {
        struct Node* node = queue[front++];
        printf("%d ", node->data);

        if (node->Lchild) {
            queue[rear++] = node->Lchild;
        }

        if (node->Rchild) {
            queue[rear++] = node->Rchild;
        }
    }
}
void  HindOrderLayer (BiTree bt){
    if(bt==NULL){
        return;
    }
    HindOrderLayer(bt->Lchild);
    HindOrderLayer(bt->Rchild);
	printf("%d ",bt->data);
}
void preorderTraversal(BiTree root) {
    if (root == NULL) {
        return;
    }

    BiTree stack[1000];
    int top = -1;

    stack[++top] = root;

    while (top >= 0) {
        BiTree node = stack[top--];

        printf("%d ", node->data);

        if (node->Rchild) {
            stack[++top] = node->Rchild;
        } 

        if (node->Lchild) {
            stack[++top] = node->Lchild;
        }
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值