非线性结构-树
实验简介
前面两章我们讲解了数据结构中的线性结构--线性表、栈和队列,这章开始以及下一章我们将讲解非线性结构树和图。
一、树
什么是树呢?树很好地反应了一种层次结构,例如下图,这就是一种树形结构,它有很多结点组成,最上面的实验楼课程结点称为树的根,结点拥有的直接子节点数称为结点的度,度为0的结点称为叶子,例如C语言、评估课这些结点,而树的度是所有结点的度中的最大值,这颗树的度就是3,一个结点的直接子结点称为它的孩子,项目课结点的孩子就是制作Markdown预览器结点,相应地项目课结点就是制作Markdown预览器结点的双亲,相同双亲的孩子结点互称为兄弟,例如C语言结点和Linux入门结点,一个结点的祖先是从根到该结点所经过的所有结点,C语言结点的祖先就是基础课和实验楼课程结点,一个结点下的所有结点称为该结点的子孙,例如实验楼课程下的所有结点都是它的子孙。树有层次之分,根记为第一层,依次类推,例如这棵树的最大层次就是3,也称为该树的深度,双亲在同一层的结点互称为堂兄弟,例如Linux入门结点和制作Markdown预览器结点。
二、二叉树
上面介绍了树,接下来我们介绍一种很常用的树结构--二叉树,它的特点是一个结点的直接子节点最多只能有两个,并且有左右之分。在二叉树中有种常见的称为完全二叉树的结构,它的特点是除最后一层外每一层的结点数为2i-1,最后一层的结点数若不满足2i-1,那么最后一层的结点是自左向右排列的,如下图。
二叉树也有顺序存储结构和链式存储结构两种,这里我们就讲下链式存储结构的代码实现(主要操作):
#include <stdio.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
#define OVERFLOW -2
#define OK 1
#define ERROR 0
typedef int Status;
typedef int TElemType;
/*
* 存储结构
*/
typedef struct BiTNode
{
TElemType data; //数据
struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;
/*
* 创建二叉树,输入0表示创建空树
*/
Status CreateBiTree(BiTree *T)
{
TElemType e;
scanf("%d", &e);
if (e == 0)
{
*T = NULL;
}
else
{
*T = (BiTree) malloc(sizeof(BiTNode));
if (!T)
{
exit(OVERFLOW);
}
(*T)->data = e;
CreateBiTree(&(*T)->lchild); //创建左子树
CreateBiTree(&(*T)->rchild); //创建右子树
}
return OK;
}
/*
* 访问元素
*/
void visit(TElemType e)
{
printf("%d ", e);
}
/*
* 先序遍历二叉树:指先访问根,然后访问孩子的遍历方式
*/
Status PreOrderTraverse(BiTree T, void (*visit)(TElemType))
{
if (T)
{
visit(T->data);
PreOrderTraverse(T->lchild, visit);
PreOrderTraverse(T->rchild, visit);
}
}
/*
* 中序遍历二叉树:指先访问左(右)孩子,然后访问根,最后访问右(左)孩子的遍历方式
*/
Status InOrderTraverse(BiTree T, void (*visit)(TElemType))
{
if (T)
{
InOrderTraverse(T->lchild, visit);
visit(T->data);
InOrderTraverse(T->rchild, visit);
}
}
/*
* 后序遍历二叉树:指先访问孩子,然后访问根的遍历方式
*/
Status PostOrderTraverse(