一、二叉树定义
二叉树是一种常用的树状数据结构,它由一组称为节点的元素组成,这些节点通过指针连接起来,形成层次结构。
在二叉树中,每个节点最多有两个子节点,分别称为左子节点和右子节点。这两个子节点可以为空,即节点没有左子节点或者右子节点
二、顺序结构存储二叉树
1.代码示例
/*===============================================
* 文件名称:seqtree.c
* 创 建 者:
* 创建日期:2023年08月11日
* 描 述:
================================================*/
#include <stdio.h>
#include <stdlib.h>
#define N 1024
typedef char seqtree_data;
// 定义二叉树结构体类型
typedef struct seq_tree
{
seqtree_data data[N] ; // 利用顺序结构存储二叉树
int len ; // 记录二叉树数据个数
}seqtree, *pseqtree;
//初始化二叉树存储空间
pseqtree init_seqtree()
{
pseqtree T = (pseqtree) malloc(sizeof(seqtree));
if( NULL == T )
{
return NULL ;
}
T->len = 0 ; // 数据开始为0个
return T ;
}
//插入数据创建二叉树
int create_seqtree(pseqtree T , int pos)
{
//输入数据
seqtree_data data ;
scanf("%c",&data) ;
getchar(); //处理垃圾字符
T->len++ ; //长度加1
//‘#’代表结束
if( '#' == data )
{
return -1 ;
}
T->data[pos] = data; //数据给到存储空间
//调用自身实现左子树创建
create_seqtree(T , 2*pos+1 ) ;
//右子树
create_seqtree(T , 2*pos+2 ) ;
return 0 ;
}
//循环输出二叉树
int show_seqtree(pseqtree T)
{
for(int i = 0 ; i < T->len ; i++ )
{
printf("%c ",T->data[i]);
}
puts("");
return 0 ;
}
int main(int argc, char *argv[])
{
pseqtree T = init_seqtree();
if( NULL == T )
{
puts("init err ");
return -1;
}
create_seqtree(T,0);
if( 0 != show_seqtree(T))
{
puts("show err");
return -1;
}
return 0;
}
2.结果
三、链式存储二叉树
1.头文件
/*===============================================
* 文件名称:linktree.h
* 创 建 者:
* 创建日期:2023年08月10日
* 描 述:
================================================*/
#ifndef _LINKTREE_H
#define _LINKTREE_H
//数据类型取别名
typedef char linktree_char;
//定义节点类型
typedef struct link_tree
{
linktree_char data;
struct link_tree * rchild ;
struct link_tree * lchild ;
}linktree , *plinktree;
//创建树
plinktree init_linktree();
//先序遍历
int precedence_linktree( plinktree T );
//中序遍历
int inorder_linktree( plinktree T);
//后续遍历
int epilogue_linktree( plinktree T);
//层次遍历
int level_linktree( plinktree T);
#endif
2.功能代码
/*===============================================
* 文件名称:linktree.c
* 创 建 者:
* 创建日期:2023年08月10日
* 描 述:
================================================*/
#include <stdio.h>
#include <stdlib.h>
#include "linktree.h"
#include "seqqueue.h"
//创建树
plinktree init_linktree()
{
//输入树的节点的数据
linktree_char c ;
scanf("%c",&c);
getchar();
if( '#' == c )//
return NULL ;
plinktree T = (plinktree) malloc(sizeof(linktree));
if( NULL == T )
return NULL;
T->data = c;
//左子树
T->lchild = init_linktree();
//右子树
T->rchild = init_linktree();
return T;
}
//先序遍历
int precedence_linktree( plinktree T )
{
if( NULL == T )
return -1;
//根
printf("%c ",T->data);
//左
precedence_linktree( T->lchild );
//右
precedence_linktree( T->rchild );
return 0;
}
//中序遍历
int inorder_linktree( plinktree T)
{
if( NULL == T )
return -1;
//左
inorder_linktree( T->lchild );
//根
printf("%c ",T->data);
//右
inorder_linktree( T->rchild );
return 0;
}
//后续遍历
int epilogue_linktree( plinktree T)
{
if( NULL == T )
return -1;
//左
epilogue_linktree( T->lchild );
//右
epilogue_linktree( T->rchild );
//根
printf("%c ",T->data);
return 0;
}
//层次遍历
int level_linktree( plinktree T)
{
if( NULL == T )
return -1;
psqueue Q = init_seqqueue();//创建一个队列
if( NULL == Q )
{
printf("init seq err");
return -1;
}
//将数根入队
if( 0 != input_seqqueue(Q,T))
{
return -2;
puts("input err ");
}
//循环入队和出队
while( 0 != empty_seqqueue(Q)) //队列为空则结束循环
{
//出队
plinktree p = out_seqqueue(Q);
if( NULL == p )
{
puts(" out err");
return -1;
}
printf("%c ",p->data);
//左节点不为空,入队
if( NULL != p->lchild)
if( 0 != input_seqqueue(Q,p->lchild))
{
puts("l input err ");
return -2;
}
//右节点不为空,入队
if( NULL != p->rchild)
if( 0 != input_seqqueue(Q,p->rchild))
{
puts("r input err ");
return -2;
}
}
return 0;
}
3.测试代码
/*===============================================
* 文件名称:main.c
* 创 建 者:
* 创建日期:2023年08月10日
* 描 述:
================================================*/
#include <stdio.h>
#include "linktree.h"
int main(int argc, char *argv[])
{
//创建树
plinktree T = init_linktree();
if( NULL == T )
{
puts("init err");
return -1;
}
//先序遍历
puts("先序遍历");
if( 0 != precedence_linktree(T))
{
puts(" pre err ");
return -1;
}
puts("");
//中序遍历
puts("中序遍历");
if( 0 != inorder_linktree(T))
{
puts(" ino err");
return -1;
}
puts("");
//后序遍历
puts("后序遍历");
if( 0 != epilogue_linktree(T))
{
puts("epi err");
return -1;
}
puts("");
//层次遍历
puts("层次遍历");
int i = level_linktree(T);
if( 0 != i)
{
printf("%d\n",i);
puts("lev err");
return -1;
}
puts("");
return 0;
}
4.运行结果
使用队列的代码
/*===============================================
* 文件名称:seqqueue.c
* 创 建 者:
* 创建日期:2023年08月09日
* 描 述:
================================================*/
#include <stdio.h>
#include "seqqueue.h"
#include <stdlib.h>
//创建
psqueue init_seqqueue()
{
psqueue Q = (psqueue ) malloc(sizeof(squeue));
if( NULL == Q )
return NULL;
Q->r = 0; //队尾
Q->f = 0;//队首
return Q;
}
//入队
int input_seqqueue(psqueue Q , queue_data value)
{
if( NULL == Q )
return -1;
if( 0 == full_seqqueue(Q))
return -2;
Q->data[Q->r] = value ;// 从队尾插入
Q->r = (Q->r+1)%N; //队尾移动一位
return 0;
}
//出队
queue_data out_seqqueue(psqueue Q)
{
//
if( NULL == Q )
return NULL;
if( 0 == empty_seqqueue(Q))
return NULL;
queue_data t = Q->data[Q->f];//从队头出队
Q->f = (Q->f+1)%N; //队头移动一位
return t;
}
//判空
int empty_seqqueue(psqueue Q)
{
if( NULL == Q )
return -1;
if( Q->r == Q->f ) // 如果出队与入队标识重合,则为空队列
return 0 ;
else
return 1;
}
//判满
int full_seqqueue(psqueue Q )
{
if( NULL == Q )
return -1;
if( Q->f == (Q->r+1)%N ) // 人为定义,在队尾离队头有一个位置时为满队列,用一个数组元素空间来判断队列是否满
return 0;
else
return 1;
}