二叉树的遍历
按照某种路径对二叉树的每个节点进行逐个访问
二叉树的层次遍历
按层次进行遍历,把二叉树的每一层从左到右遍历.
#include<stdio.h>
#include<stdlib.h>
//链式队列
//队列节点结构
typedef struct QNode {
char data;//树节点的数据域入队
struct QNode* next;
}QNode;
//队列
typedef struct Queue {
QNode* f;
QNode* r;
}Queue;
Queue InitQueue() {
Queue q;
q.f = (QNode*)malloc(sizeof(QNode));
if (q.f == NULL) {
printf("内存申请失败\n");
return q;
}
q.f->next = NULL;
q.r = q.f;
return q;
}
void EnQueue(Queue* q, char x) {
QNode* s = (QNode*)malloc(sizeof(QNode));
if (s == NULL) {
printf("内存申请失败\n");
return;
}
s->data = x;
s->next = NULL;
q->r->next = s;
q->r = s;
return;
}
int empty(Queue* q) {
if (q->f->next == NULL) {
return 1;
}
return 0;
}
char DeQueue(Queue* q) {
char x = ' ';
if (empty(q)) {
printf("队列为空无法出队\n");
return x;
}
else {
QNode* p = q->f->next;
x = p->data;
if (q->f->next == q->r)//队列中只有一个节点
{
q->r = q->f;
}
q->f->next = p->next;
free(p);
p = NULL;
}
return x;
}
//树的结构----二叉链表
//节点结构
typedef struct BTNode {
char data;
struct BTNode* l;
struct BTNode* r;
}BTNode,*BTree;
BTree InitTree(char root) {
BTNode* rt = (BTNode*)malloc(sizeof(BTNode));
if (rt == NULL) {
printf("内存申请失败\n");
return rt;
}
rt->data = root;
rt->l = NULL;
rt->r = NULL;
return rt;
}
BTNode* Find(BTree root, char x) {
if (root == NULL) {
return NULL;
}
if (root->data == x) {
return root;
}
if (root->l != NULL) {
BTNode* ans = Find(root->l,x);
if (ans != NULL && ans->data == x) {
return ans;
}
}
if (root->r != NULL) {
BTNode* ans = Find(root->r,x);
if (ans != NULL && ans->data == x) {
return ans;
}
}
return NULL;
}
BTree Insert(BTree root, char x, char fx, int flag) {
BTNode* f = Find(root, fx);//父亲节点的位置
BTNode* s = (BTNode*)malloc(sizeof(BTNode));
if (s == NULL) {
printf("内存申请失败\n");
return root;
}
s->data = x;
s->l = NULL;
s->r = NULL;
if (flag == 0)//左孩子
{
f->l = s;
}
else {
f->r = s;
}
return root;
}
//-------------------------------------------------------------
//层次遍历
void LevelOrderBT(BTree root) {
Queue q = InitQueue();
EnQueue(&q,root->data);
char x;
BTNode* p = NULL;
while (!empty(&q)) {
x = DeQueue(&q);
printf("%c ", x);
p = Find(root, x);
if (p->l != NULL) {
EnQueue(&q, p->l->data);
}
if (p->r != NULL) {
EnQueue(&q, p->r->data);
}
}
}
//先序遍历
void PreOrderBT(BTree root) {
if (root == NULL) {
return NULL;
}
//1.访问根节点
printf("%c ", root->data);
//先序遍历左子树
PreOrderBT(root->l);
//先序遍历右子树
PreOrderBT(root->r);
}
//中序遍历
void InOrderBT(BTree root) {
if (root == NULL) {
return NULL;
}
//中序遍历左子树
InOrderBT(root->l);
//访问根节点
printf("%c ", root->data);
//中序遍历右子树
InOrderBT(root->r);
}
//后序遍历
void PostOrderBT(BTree root) {
if (root == NULL) {
return NULL;
}
//后序遍历左子树
PostOrderBT(root->l);
//后序遍历右子树
PostOrderBT(root->r);
//访问根节点
printf("%c ", root->data);
}
int main() {
int n;
int flag;//0是左孩子 1是右孩子
scanf("%d", &n);
getchar();
char x, fx;
scanf("%c", &x);
BTree root = InitTree(x);
for (int i = 0; i < n - 1; i++) {
getchar();
scanf("%c %c %d", &x, &fx,&flag);
Insert(root, x, fx, flag);
}
LevelOrderBT(root);
printf("\n");
PreOrderBT(root);
printf("\n");
InOrderBT(root);
printf("\n");
PostOrderBT(root);
printf("\n");
return 0;
}
/*
9
A
B A 0
E A 1
C B 1
F E 1
D C 0
G F 0
H G 0
K G 1
*/
首先先搭建队列的结构,这里采用链式的队列.
队列的节点数据域有两种选择:1.直接记录节点的数据.优点是队列的结构简单明了.缺点在于进行后续出队操作时需要通过Find函数找到相对应的节点.2.记录节点地址.优点缺点与前者相反.在这里我们选择第一种方法.队列的结构只需要一个头指针和一个尾指针即可.队列操作 树的二叉链表以及初始化操作均在以前的博客中提及,需要了解的读者可自行阅读,本文重点在于深度层级遍历.
层级遍历: 初始化队列q后,先将根节点入队.只要队列不空那么就让队首元素出队 访问,同时把队首元素的左右子节点分别入队.直到队列为空,整棵树都遍历完毕.
二叉树的深度遍历
二叉树的深度遍历分为三种:前序遍历 中序遍历 后序遍历
二叉树可以抽象为根节点,左子树,右子树.而这三种遍历方式的区别就是遍历这三者的顺序,例如前序遍历就是先遍历根节点再遍历左子树最后遍历右子树.而对不同节点的操作逻辑都是相同的,所以我们可以用递归来操作.
//先序遍历
void PreOrderBT(BTree root) {
if (root == NULL) {
return NULL;
}
//1.访问根节点
printf("%c ", root->data);
//先序遍历左子树
PreOrderBT(root->l);
//先序遍历右子树
PreOrderBT(root->r);
}
//中序遍历
void InOrderBT(BTree root) {
if (root == NULL) {
return NULL;
}
//中序遍历左子树
InOrderBT(root->l);
//访问根节点
printf("%c ", root->data);
//中序遍历右子树
InOrderBT(root->r);
}
//后序遍历
void PostOrderBT(BTree root) {
if (root == NULL) {
return NULL;
}
//后序遍历左子树
PostOrderBT(root->l);
//后序遍历右子树
PostOrderBT(root->r);
//访问根节点
printf("%c ", root->data);
}
先判断根节点是否为空,然后分别按照不同的顺序递归调用本函数.