前面有一期是关于二叉树的三种遍历方式实现代码,那是属于简单版,结合二叉树的顺序存储。而这期文章是结合二叉树的链式存储来解决四种遍历(包括前面因为复杂麻烦没说的层次遍历),这主要结合队列的知识来实现层次遍历代码。下面一起来看看代码吧。
完整代码:
#include<stdio.h>
#include<stdlib.h>
struct tree_node //定义树结点
{
char id;
struct tree_node* left;
struct tree_node* right;
};
struct queue_node //定义队列结点
{
struct tree_node* treenode;
struct queue_node* next;
};
struct queue //定义队列结构类型
{
struct queue_node* front;
struct queue_node* rear;
};
//几个自定义
typedef struct tree_node TreeNode;
typedef struct tree_node* Tree;
typedef struct queue_node QueueNode;
typedef struct queue Queue;
void CreateTree(Tree*);
int GetHeight(Tree);
int MaxOfTwo(int, int);
int GetNodeNumber(Tree);
void PreShow(Tree);
void MidShow(Tree);
void BackShow(Tree);
void LevelShow(Tree);
void InitQueue(Queue*);
bool IsQueueEmpty(Queue*);
void InQueue(Queue*, QueueNode*);
void OutQueue(Queue*, QueueNode**);
void ClearTree(Tree*);
bool IsTreeEmpty(Tree);
//创建二叉树
void CreateTree(Tree* T)
{
char ch;
scanf_s("%c", &ch,250);
if (ch == '*')//第一个根节点不能为空,之后若为空,就创建右子树
{
*T = NULL;
}
else
{
*T = (Tree)malloc(sizeof(TreeNode)); // 注意第一个元素是做根节点
(*T)->id = ch;
CreateTree(&(*T)->left);//创建左子树,从上到下依次为输入的顺序,
CreateTree(&(*T)->right);//创建右子树
}
}
//两数较大值
int MaxOfTwo(int a, int b)
{
if (a >= b)
{
return a;
}
else
{
return b;
}
}
//获得二叉树的高度
int GetHeight(Tree T)
{
if (T)
{
return MaxOfTwo(GetHeight(T->left), GetHeight(T->right)) + 1;
}
else
{
return 0;
}
}
//获得二叉树的节点数
int GetNodeNumber(Tree T)
{
if (T)
{
return GetNodeNumber(T->left) + GetNodeNumber(T->right) + 1;//+1是加上根节点
}
else
{
return 0;
}
}
//前序遍历
void PreShow(Tree T)
{
if (!T)
{
return;
}
printf("%c ", T->id);
PreShow(T->left);
PreShow(T->right);
}
//中序遍历
void MidShow(Tree T)
{
if (!T)
{
return;
}
MidShow(T->left);
printf("%c ", T->id);
MidShow(T->right);
}
//后序遍历
void BackShow(Tree T)
{
if (!T)
{
return;
}
BackShow(T->left);
BackShow(T->right);
printf("%c ", T->id);
}
//初始化队列
void InitQueue(Queue* q)
{
q->front = NULL;
q->rear = NULL;
}
//队列是否为空
bool IsQueueEmpty(Queue* q)
{
if (q->front)
{
return false;
}
else
{
return true;
}
}
//进队
void InQueue(Queue* q, QueueNode* p)
{
if (IsQueueEmpty(q))//若为空,则头指针和尾指针都指向p
{
q->front = p;
q->rear = p;
}
else//链式进入队列
{
q->rear->next = p;
q->rear = p;
}
}
//出队
void OutQueue(Queue* q, QueueNode** p)
{
*p = q->front;
if (q->front == q->rear) //只有1个节点
{
q->front = NULL;
q->rear = NULL;
}
else
{
q->front = q->front->next;
}
}
//层序遍历
void LevelShow(Tree T)
{
if (!T)
{
return;
}
Queue m_queue;
Queue* Q;
QueueNode* p, * q;
Q = &m_queue;
InitQueue(Q); //队列初始化
p = (QueueNode*)malloc(sizeof(QueueNode));
p->next = NULL;
p->treenode = T;
InQueue(Q, p); //根节点进队
while (!IsQueueEmpty(Q))
{
OutQueue(Q, &q); //当前队首节点出队
printf("%c ", q->treenode->id);
//按照先左后右的顺序,这里并不用到递归
if (q->treenode->left) //左孩子非空,则左孩子进队
{
p = (QueueNode*)malloc(sizeof(QueueNode));
p->next = NULL;
p->treenode = q->treenode->left;
InQueue(Q, p);
}
if (q->treenode->right) //右孩子非空,则右孩子进队
{
p = (QueueNode*)malloc(sizeof(QueueNode));
p->next = NULL;
p->treenode = q->treenode->right;
InQueue(Q, p);
}
}
}
//清除二叉树
void ClearTree(Tree* T)
{
if (!*T)
{
return;
}
ClearTree(&(*T)->left);
ClearTree(&(*T)->right);
free(*T);
*T = NULL;
}
//二叉树是否为空
bool IsTreeEmpty(Tree T)
{
if (T)
{
return false;
}
else
{
return true;
}
}
int main(void)
{
Tree t;
printf("输入二叉树的前序遍历序列,用*代替空节点:\n");
CreateTree(&t);
printf("\n二叉树创建完毕,高度为%d,节点数为%d。", GetHeight(t), GetNodeNumber(t));
printf("\n\n前序遍历:");
PreShow(t);
printf("\n\n中序遍历:");
MidShow(t);
printf("\n\n后序遍历:");
BackShow(t);
printf("\n\n层序遍历:");
LevelShow(t);
ClearTree(&t);
if (IsTreeEmpty(t))
{
printf("\n\n二叉树已经删除。");
}
printf("\n\n");
return 0;
}
程序执行图:
只要大家去好好理解一下层次遍历,会发现其实一点都不难,都没用到递归,只是结合到队列的知识从而程序代码量多了点。
本贴为博主亲手整理。如有错误,请评论区指出,一起进步。谢谢大家的浏览.