二叉树指每个节点最多含有两个子树的树称为二叉树,二叉树与普通有序树不同, 二叉树严格区
分左孩子和右孩子, 即使只有一个子节点也要区分左右。所以可以为每个节点设计一个包含数据和该节点的左孩子节点和右孩子节点的指针的结构体。
二叉树由一个根结点和两个互不相交的被称为根的左子树和右子树组成。左子树和右子树又分别是一棵二叉树。所以二叉树也是递归定义的,就可以通过递归实现对二叉树的存储和遍历。
二叉树一般采用链式存储,其节点结构体定义如下:
typedef char data_t;//数据类型根据实际情况确定,目前暂定为字符型
typedef struct tree_node
{
data_t data;//数据域
struct tree_node *l_child;//指向当前节点的左孩子节点
struct tree_node *r_child;//指向当前节点的右孩子节点
}T_node;
二叉树的创建:
注:输入的字符‘#’表示该节点为空节点,不存数据
T_node *create_tree()
{
char ch;
scanf("%c",&ch);
if(ch=='#'){
//printf("none node\n");
return NULL;
}
else{
T_node *root=(T_node *)malloc(sizeof(T_node));
if(NULL==root)
{
printf("malloc error\n");
return NULL;
}
root->data=ch;
root->l_child=create_tree();
root->r_child=create_tree();
return root;
}
}
二叉树的遍历方式一:先序遍历
即先访问根结点;再遍历左子树;最后遍历右子树,简记为根左右。要注意的是每访问一个节点要考虑其是否有左孩子节点和右孩子节点,每一个节点都可以看成是一颗由该节点及其祖孙节点构成的树。
void preorder_traver(T_node * root)
{
if(root==NULL){
return ;
}
else{
printf("%c ",root->data);//此处访问方式采用标准输出的方式易于展示
preorder_traver(root->l_child);
preorder_traver(root->r_child);
}
}
二叉树的遍历方式二:中序遍历
即先访问左子树,再访问根节点,再访问右子树,简记为左根右。
void inorder_traver(T_node * root)
{
if(root==NULL){
return ;
}
else{
inorder_traver(root->l_child);
printf("%c ",root->data);
inorder_traver(root->r_child);
}
}
二叉树的遍历方式三:后序遍历
即先访问左子树,再访问右子树,再访问根节点,简记为左右根。
void postorder_traver(T_node * root)
{
if(root==NULL){
return ;
}
else{
postorder_traver(root->l_child);
postorder_traver(root->r_child);
printf("%c ",root->data);
}
}
二叉树的遍历方式三:层次遍历
层次遍历指从二叉树的第一层(根节点)开始,从上至下逐层遍历,在同一层中,则按照从左到右的顺序对节点逐个访问。利用队列能够较好实现,先将二叉树根结点入队,访问该结点,若它有左子树,则将左子树根结点入队;若它有右子树,则将右子树根结点入队再将该根结点出队。访问然后出队头结点…如此反复,直至队列为空。
void level_traver(T_node *root)
{
int front,rear;//顺序队列头尾指针
T_node *Q[64];//数组每个元素存储树的每个节点的地址,注意数组的大小要大于整个树的总节点个数
if(root==NULL)
{
printf("tree none \n");
return ;
}
for(rear=1;rear<64;rear++)Q[rear]=NULL;//指针数组初始化
front=rear=1;
Q[rear]=root;
while(Q[front]!=NULL)
{
printf("%c ",Q[front]->data);
if(Q[front]->l_child != NULL)
{
rear++;
Q[rear]=Q[front]->l_child;
}
if(Q[front]->r_child != NULL)
{
rear++;
Q[rear]=Q[front]->r_child;
}
front++;
}
}
假设现在如下这颗二叉树:
则先序遍历结果:abcdefghk
中序遍历结果:bdcaehgkf
后序遍历结果:dcbhkgfea
层次遍历结果:abecfdghk
二叉树的测试完整代码如下:
/*===============================================
* 文件名称:tree.h
* 创 建 者: xm
* 创建日期:2022年08月02日
* 描 述:
================================================*/
#ifndef _TREE_
#define _TREE_
#include <stdio.h>
#include <stdlib.h>
typedef char data_t;
typedef struct tree_node
{
data_t data;//数据域
struct tree_node *l_child;//指向当前节点的左孩子节点
struct tree_node *r_child;指向当前节点的右孩子节点
}T_node;
//先序遍历,根左右
T_node *create_tree();
void preorder_traver(T_node *root);
//中序遍历,左根右
void inorder_traver(T_node *root);
//后序遍历,左右根
void postorder_traver(T_node *root);
//层次遍历
void level_traver(T_node *root);
#endif
/*===============================================
* 文件名称:tree.c
* 创 建 者: xm
* 创建日期:2022年08月02日
* 描 述:
================================================*/
#include "tree.h"
T_node *create_tree()
{
char ch;
scanf("%c",&ch);
if(ch=='#'){
//printf("none node\n");
return NULL;
}
else{
T_node *root=(T_node *)malloc(sizeof(T_node));
if(NULL==root)
{
printf("malloc error\n");
return NULL;
}
root->data=ch;
root->l_child=create_tree();
root->r_child=create_tree();
return root;
}
}
//先序遍历,根左右
void preorder_traver(T_node * root)
{
if(root==NULL){
return ;
}
else{
printf("%c ",root->data);
preorder_traver(root->l_child);
preorder_traver(root->r_child);
}
}
//中序遍历,根左右
void inorder_traver(T_node * root)
{
if(root==NULL){
return ;
}
else{
inorder_traver(root->l_child);
printf("%c ",root->data);
inorder_traver(root->r_child);
}
}
//后序遍历,根左右
void postorder_traver(T_node * root)
{
if(root==NULL){
return ;
}
else{
postorder_traver(root->l_child);
postorder_traver(root->r_child);
printf("%c ",root->data);
}
}
//利用队列实现层次遍历
void level_traver(T_node *root)
{
int front,rear;//顺序队列头尾指针
T_node *Q[64];//数组每个元素存储树的每个节点的地址,注意数组的大小要大于整个树的总节点个数
if(root==NULL)
{
printf("tree none \n");
return ;
}
for(rear=1;rear<64;rear++)Q[rear]=NULL;//指针数组初始化
front=rear=1;
Q[rear]=root;
while(Q[front]!=NULL)
{
printf("%c ",Q[front]->data);
if(Q[front]->l_child != NULL)
{
rear++;
Q[rear]=Q[front]->l_child;
}
if(Q[front]->r_child != NULL)
{
rear++;
Q[rear]=Q[front]->r_child;
}
front++;
}
}
/*===============================================
* 文件名称:main.c
* 创 建 者: xm
* 创建日期:2022年08月02日
* 描 述:
================================================*/
#include "tree.h"
int main(int argc, char *argv[])
{
T_node *root=create_tree();
puts("先序遍历");
preorder_traver(root);
printf("\n中序遍历\n");
inorder_traver(root);
printf("\n后序遍历\n");
postorder_traver(root);
puts("");
printf("层次遍历\n");
level_traver(root);
return 0;
}
输入ab#cd###e#fgh##k###
测试得: