C语言实现二叉树的递归与非递归遍历

最近整理了一下二叉树的递归和非递归的代码实现,有需要的小伙伴可以参考一下哦!

  1. 二叉树的创建
  2. 二叉树的前序、中序、后序递归实现
  3. 二叉树的前序、中序、后序非递归实现
  4. 求二叉树的深度、层序遍历

Tree.h

#pragma once

//二叉树的存储结构,一个数据域,2个指针域
typedef struct BiTNode
{
	char data;
	struct BiTNode* lchild, * rchild;
}BiTNode, *BiTree;

typedef struct LinkNode {	//声明链式节点
	BiTree data;
	struct LinkNode* next;
}LinkNode;

typedef struct {
	LinkNode* front, * rear;
}LinkQueue;

void InitQueue(LinkQueue& Q);	//初始化链式队列
bool IsEmpty(LinkQueue Q);	//判队列是否为空
void EnQueue(LinkQueue& Q, BiTree T);	//入队
bool DeQueue(LinkQueue& Q, BiTree &T);	//出队

void createBiTree(BiTree* T, char  arr[], int i, int len);//数组创建二叉树
void PreOrderTraverse(BiTree T);//二叉树的前序遍历
void InOrderTraverse(BiTree T);//二叉树的中序遍历
void PostOrderTraverse(BiTree T);//后序遍历
void CreateBiTree(BiTree* T);//递归创建二叉树
void PreInCreateT(BiTree* T);//已知先序遍历和中序遍历建立二叉树
int Btdepth(BiTree T);//非递归求二叉树的深度
int Btdepth2(BiTree T);//递归求二叉树的深度
int Leaftree(BiTree T); //递归求出二叉树叶子节点数
void PreKTraverse(BiTree T, int k);	//非递归输出先序遍历第k个节点的值
void PreTraverse(BiTree T);		//非递归实现先序遍历
void InTraverse(BiTree T);		//非递归实现中序遍历
void PostTraverse(BiTree T);	//非递归实现后序遍历
void LevelTraverse(BiTree T);	//非递归实现层序遍历

TreeProblem.cpp

#include<stdio.h>
#include<stdlib.h>
#include"Tree.h"


//初始化链式队列
void InitQueue(LinkQueue& Q) {
    Q.front = Q.rear = (LinkNode*)malloc(sizeof(LinkNode)); //建立头结点
    Q.front->next = NULL;     //初始为空
}
//判队列是否为空
bool IsEmpty(LinkQueue Q) {
    if (Q.front == Q.rear) return true;
    else return false;
}
//入队
void EnQueue(LinkQueue& Q, BiTree T) {
    LinkNode  *s = (LinkNode*)malloc(sizeof(LinkNode));      //创建新节点
    s->data = T; s->next = NULL;
    Q.rear->next = s;
    Q.rear = s;
}
//出队
bool DeQueue(LinkQueue& Q, BiTree &T) {
    if (Q.front == Q.rear) return false;    //队列空报错
    LinkNode* p = Q.front->next;
    T = p->data;    
    Q.front->next = p->next;
    if (Q.rear == p)
        Q.rear = Q.front;       //只有一个元素,删除后变空
    free(p);
    return true;
}

#define MaxSize 50
void visit(BiTree T) {
    printf("%c ", T->data);    //输出节点值
}
//递归创建二叉树
void CreateBiTree(BiTree* T)//创建二叉树
{
    char ch;
    scanf_s("%c", &ch);
    if (ch == '#')
        *T = NULL;
    else
    {
        *T = (BiTree)malloc(sizeof(BiTNode));
        if (!*T)
            exit(-1);
        (*T)->data = ch;
        CreateBiTree(&(*T)->lchild);
        CreateBiTree(&(*T)->rchild);
    }
}

//数组创建二叉树
void createBiTree(BiTree* T, char arr[], int i, int len) {
    
        char temp = arr[i];
        //printf("%c ", temp);
        if (temp == '#') {
            (*T) = NULL;
        }
        else {
            (*T) = (BiTree)malloc(sizeof(BiTNode));
            if (!*T)
                exit(-1);
            (*T)->data = arr[i];

            createBiTree(&(*T)->lchild, arr, i++, len);
            createBiTree(&(*T)->rchild, arr, i++, len);
        }
    }

//二叉树的前序遍历
void PreOrderTraverse(BiTree T) {//二叉树的先序遍历
    if (T == NULL)
        return;
    printf("%c ", T->data);
    PreOrderTraverse(T->lchild);
    PreOrderTraverse(T->rchild);
}

//二叉树的中序遍历
void InOrderTraverse(BiTree T)//二叉树的中序遍历
{
    if (T == NULL)
        return;
    InOrderTraverse(T->lchild);
    printf("%c ", T->data);
    InOrderTraverse(T->rchild);
}

//二叉树的后序遍历
void PostOrderTraverse(BiTree T)//后序遍历
{
    if (T == NULL)
        return;
    PostOrderTraverse(T->lchild);
    PostOrderTraverse(T->rchild);
    printf("%c ", T->data);
}

//非递归求二叉树的深度
int Btdepth(BiTree T) {
    return 0;
}

//递归求二叉树的深度
int Btdepth2(BiTree T) {
    if (T == NULL) {
        return 0;
    }
    int ldepth = Btdepth2(T->lchild);// 左子树高度
    int rdepth = Btdepth2(T->rchild);// 右子树高度
    if (ldepth > rdepth) return ldepth + 1;
    else return rdepth + 1;

}

//递归求出叶子节点数
int Leaftree(BiTree T) {
    if (!T) {
        return 0;   //空树
    }
    if (!T->rchild && !T->lchild) {
        return 1;
    }
    else return Leaftree(T->lchild) + Leaftree(T->rchild);
}

//已知二叉树的前序跟中序遍历构造二叉树
void PreInCreateT(BiTree* T) {

}

//非递归输出先序遍历第k个节点的数据值
void PreKTraverse(BiTree T,int k) {
    BiTree p = T;     //p是遍历指针;
    BiTree stack[MaxSize];  //初始化栈
    int top = -1; int count = 0;//用于计数
    
    while (p || top != -1) {
        if (p) {
            //visit(p);
            count++;
            stack[++top] = p;   //节点入栈
            if (count == k)visit(p);
            p = p->lchild;
        }
        else {
            p = stack[top--];   //节点出栈
            p = p->rchild;
        }
    }
}

//非递归实现先序遍历
void PreTraverse(BiTree T) {
    BiTree p = T;     //p是遍历指针;
    BiTree stack[MaxSize];  //初始化栈
    int top = -1;

    while (p || top != -1) {
        if (p) {
            visit(p);   // 访问节点
            stack[++top] = p;   //节点入栈
            p = p->lchild;
        }
        else {
            p = stack[top--];   //节点出栈
            p = p->rchild;
        }
    }
}

//非递归实现中序遍历
void InTraverse(BiTree T) {
    BiTree p = T;     //p是遍历指针;
    BiTree stack[MaxSize];  //初始化栈
    int top = -1;

    while (p || top != -1) {
        if (p) {
            stack[++top] = p;   //节点入栈
            p = p->lchild;
        }
        else {
            p = stack[top--];   //节点出栈
            visit(p);   // 访问节点
            p = p->rchild;
        }
    }
}

//非递归的后序遍历
void PostTraverse(BiTree T) {
    BiTree p = T;
    BiTree stack[MaxSize];  //初始化一个栈
    int top = -1;
    BiTree r = NULL;   //用于记录刚访问的节点

    while (top != -1 || p) {    //栈不空或者树不空时
        if (p) {
            stack[++top] = p;   //将p节点入栈
            p = p->lchild;  //继续向左走
        }
        else {
            p = stack[top]; //读取栈顶元素
            if (p->rchild && p->rchild != r) {  //如果有孩子不空且未被访问入栈
                p = p->rchild;  //转向右;
                stack[++top] = p;   //将右孩子入栈;
                p = p->lchild;  //继续往左探;
            }
            else {  //当右孩子为空或者右孩子已经被访问过则输出节点
                p = stack[top--];   //输出节点然后访问 
                visit(p);
                r = p;  //将刚访问过的节点赋值给r
                p = NULL;   //访问完将P初始化为空
            }
        }
    }
}

//非递归实现层序遍历

void LevelTraverse(BiTree T) {
    LinkQueue Q;
    InitQueue(Q);   //初始化队列
    BiTree p = T;
    EnQueue(Q,p); //入队
    while (!IsEmpty(Q) {  //队列不空时执行
        DeQueue(Q, p);
        visit(p);  
        //访问节点p
        if (p->lchild != NULL) {    //如果左子树不空,左子树根节点入队
            EnQueue(Q, p->lchild);
        }
        if (p->rchild != NULL) {    //如果右子树不空,右子树根节点入队
            EnQueue(Q, p->rchild);
        }
    }
}


TestTree.cpp

#include<stdio.h>
#include"Tree.h"

int main()
{
    BiTree T;  //ABD##E##CF##G##
    CreateBiTree(&T);//递归创建二叉树
    PreOrderTraverse(T);
    printf("\n");
    InOrderTraverse(T);
    printf("\n");
    PostOrderTraverse(T);
    printf("\n");
    printf("你所创建的二叉树的高度为:%d\n",Btdepth2(T));//递归输出二叉树高度
    printf("二叉树的叶子节点数为:%d\n", Leaftree(T));
    printf("非递归输出先序遍历的第k个节点的值:"); PreKTraverse(T,4); printf("\n");
    printf("先序非递归遍历:"); PreTraverse(T); printf("\n");
    printf("中序非递归遍历:"); InTraverse(T); printf("\n");
    printf("后序非递归遍历:"); PostTraverse(T); printf("\n");
    printf("层序非递归遍历:"); LevelTraverse(T); printf("\n");
}

附上一张测试的运行结果:
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值