最近整理了一下二叉树的递归和非递归的代码实现,有需要的小伙伴可以参考一下哦!
- 二叉树的创建
- 二叉树的前序、中序、后序递归实现
- 二叉树的前序、中序、后序非递归实现
- 求二叉树的深度、层序遍历
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");
}
附上一张测试的运行结果: