/*
Name: 二叉链表实现二叉树
Copyright:
Author:
Date:
Description:
*/
#ifndef BINTREE_H_INCLUDED
#define BINTREE_H_INCLUDED
#include <stdlib.h>
#include "ds.h"
//数据元素的缺省类型用char
#ifndef ElemType
#define ElemType char
#define ELEMTYPE_TAG
#endif
/*下面使用TElemType如同ElemType*/
#define TElemType ElemType
///
// 二叉链表类型
typedef struct BiTNode {
TElemType data;
struct BiTNode *lchild, *rchild; //左右孩子指针
} BiTNode, *BiTree;
///
// 二叉链表的基本操作
//新建二叉链表结点
BiTree MakeNode(TElemType e, BiTree lch, BiTree rch)
{
BiTree p = (BiTree)malloc(sizeof(BiTNode));
p->data = e;
p->lchild = lch;
p->rchild = rch;
return p;
}
//按先序次序输入二叉树中的结点值(字符)构造二叉树
Status CreateBiTree(BiTree &T)
{
char ch;
read(ch); // NOTE: 这里用字符类型
if( ch==' ' ) //空格代表空指针
T = 0;
else {
//建立结点
T = (BiTree)malloc(sizeof(BiTNode));
T->data = ch;
//-------------------------------------
// TODO (#1#):建立左子树和右子树
CreateBiTree(T->lchild);
CreateBiTree(T->rchild);
//-------------------------------------
}
return OK;
}
//销毁二叉树
Status DestroyBiTree(BiTree &T)
{
//-------------------------------------
// TODO (#1#): 销毁二叉树,释放所有结点
if(!T)
return ERROR;
else{
DestroyBiTree(T->lchild);
DestroyBiTree(T->rchild);
free(T);
}
return OK;
//-------------------------------------
}
//先序遍历二叉树T,对每个结点数据调用Visit函数
Status PreOrderTraverse(BiTree T, Status(*Visit)(TElemType))
{
//-------------------------------------
// TODO (#1#): 先序遍历二叉树
if(!T)
return OK;
else{
Visit(T->data);
PreOrderTraverse(T->lchild,Visit);
PreOrderTraverse(T->rchild,Visit);
return OK;
}
return ERROR;
//-------------------------------------
}
//中序遍历二叉树T,对每个结点数据调用Visit函数
Status InOrderTraverse(BiTree T, Status(*Visit)(TElemType))
{
//-------------------------------------
// TODO (#1#): 中序遍历二叉树
if(!T)
return OK;
else{
InOrderTraverse(T->lchild,Visit);
Visit(T->data);
InOrderTraverse(T->rchild,Visit);
return OK;
}
return ERROR; //-------------------------------------
}
//后序遍历二叉树T,对每个结点数据调用Visit函数
Status PostOrderTraverse(BiTree T, Status(*Visit)(TElemType))
{
//-------------------------------------
// TODO (#1#): 后序遍历二叉树
if(!T)
return OK;
else{
PostOrderTraverse(T->lchild,Visit);
PostOrderTraverse(T->rchild,Visit);
Visit(T->data);
return OK;
}
return ERROR; //-------------------------------------
}
//按层次顺序遍历二叉树T,对每个结点数据调用Visit函数
Status LevelOrderTraverse(BiTree T, Status(*Visit)(TElemType))
{
//-------------------------------------
// TODO (#1#): 按层次遍历二叉树
BiTree Q[100];
int front=0,rear=0;
if(!T)
return ERROR;
else
{
Visit(T->data);
Q[rear]=T; rear=(rear+1)%100;
while(front!=rear){
BiTree p=Q[front];
front=(front+1)%100;
if(p->lchild){
Visit(p->lchild->data);
Q[rear]=p->lchild;
rear=(rear+1)%100;
}
if(p->rchild){
Visit(p->rchild->data);
Q[rear]=p->rchild;
rear=(rear+1)%100;
}
}
return OK;
}
}
//以直观方式打印二叉树
void PrintTree(BiTree t, int level=0)
{
int i;
if(t) {
PrintTree(t->rchild, level+1);
for(i=0; i<level; i++) printf(" ");
write(t->data); write('\n');
PrintTree(t->lchild, level+1);
}
}
//取消缺省类型的定义以免影响其它部分
#ifdef ELEMTYPE_TAG
#undef ElemType
#undef ELEMTYPE_TAG
#endif
#endif //BINTREE_H_INCLUDED
/****************************************************
@Title: 数据结构实验
@Name: <实验6-3> 遍历二叉树及其应用
@Object:
[实验目的]
实现二叉树的二叉链表存储结构;
实现先序、中序和后序遍历二叉树;
遍历二叉树的应用:计算叶子结点,二叉树深度等
[实验提示]
1. 在 bintree.h 中实现二叉树的基本操作
2. 在 dsp0603.cpp 中编写应用遍历二叉树的算法
@Include:
bintree.h [*]
二叉树的二叉链表实现
@Usage:
请查看"TO-DO列表",根据要求完成代码
@Copyright: BTC 2004, Zhuang Bo
@Author: Zhuang Bo
@Date: 2004
@Description:
*****************************************************/
#include <stdio.h>
#include <stdlib.h>
#define ElemType char //二叉树中数据元素类型
#include "bintree.h" //二叉树的实现
//打印结点数据(作为Visit函数)
Status print(char);
//计算二叉树中叶子结点的个数
int LeafCount(BiTree bt);
//计算二叉树的深度
int Deapth(BiTree bt);
//按缩进方式打印二叉树
void PrintTreeIndent(BiTree bt, int indent);
///
// 主程序
int main()
{
BiTree bt = 0;
//建立二叉树
printf("建立二叉树(按先序输入二叉树中的结点,空格表示空树)\n");
if( CreateBiTree(bt)==ERROR ) {
printf("ERROR: call CreateBiTree\n");
system("pause");
exit(1);
}
PrintTree(bt);
//遍历二叉树
printf("\n先序遍历: ");
if( PreOrderTraverse(bt,print)==ERROR )
printf("ERROR: call PreOrderTraverse\n");
printf("\n中序遍历: ");
if( InOrderTraverse(bt,print)==ERROR )
printf("ERROR: call InOrderTraverse\n");
printf("\n后序遍历: ");
if( PostOrderTraverse(bt,print)==ERROR )
printf("ERROR: call PostOrderTraverse\n");
printf("\n按层遍历: ");
if( LevelOrderTraverse(bt,print)==ERROR )
printf("ERROR: call LevelOrderTraverse\n");
//二叉树的应用
printf("\n二叉树中叶子结点的个数: %d\n", LeafCount(bt));
printf("\n二叉树的深度: %d\n", Deapth(bt));
printf("\n按缩进形式打印:\n");
PrintTreeIndent(bt,1);
//销毁二叉树
DestroyBiTree(bt);
system("pause"); //暂停以便查看结果
}
///
// 函数实现
//打印结点数据
Status print(char ch)
{
putchar(ch);
return OK;
}
//计算二叉树中叶子结点的个数
int LeafCount(BiTree bt)
{
//-------------------------------------
// TODO (#1#):计算二叉树中叶子结点的个数
if(!bt)
return 0;
if(!bt->lchild&&!bt->rchild)
return 1;
int left=LeafCount(bt->lchild);
int right=LeafCount(bt->rchild);
return left+right;
}
//计算二叉树的深度
int Deapth(BiTree bt)
{
//-------------------------------------
// TODO (#1#):计算二叉树的深度
if(!bt)
return 0;
else{
int lh=Deapth(bt->lchild);
int rh=Deapth(bt->rchild);
return 1+((lh>rh)?lh:rh);
}
}
//按缩进方式打印二叉树
void PrintTreeIndent(BiTree bt, int indent)
{
//-------------------------------------
// TODO (#1#):按缩进方式(凹入表示法)打印二叉树
int i;
if (bt)
{
for (i=1; i<indent; i++) printf(" "); //输出indent个空格
printf("%c\n", bt->data);
PrintTreeIndent (bt->lchild, indent+3);
PrintTreeIndent (bt->rchild, indent+3);
}
}
/*
Name: 类C通用模块
Copyright: BTC 2004
Author: Zhuang Bo
Date: 2004
Description:
[Constants]
TRUE/FALSE/OK/ERROR/INFEASIBLE/OVERFLOW
[Types]
Status
[Functions]
max(a,b)
min(a,b)
read(char/int/float/double/char*)
write(char/int/float/double/char*)
*/
#ifndef _DS_H_
#define _DS_H_
// 函数结果状态代码
const int TRUE = 1;
const int FALSE = 0;
const int OK = 1;
const int ERROR = 0;
const int INFEASIBLE = -1;
const int OVERFLOW = -2;
// Status 是函数的类型,其值是函数结果状态代码
typedef int Status;
//基本函数
#define max(a,b) (((a)<(b))?(b):(a))
#define min(a,b) (((a)<(b))?(a):(b))
#include <stdio.h>
//不用格式串的输入输出(目的是为了方便书写算法)
// 比如输入一个基本类型(char, int, float, double, char*)的
// 变量 x,可以直接用 read(x);输入,而打印则用 write(x);。
// 对于自定义类型,可以继续扩充。
inline void read(char& e) { e = getchar(); }
inline void read(int& e) { scanf("%d", &e); }
inline void read(float& e) { scanf("%f", &e); }
inline void read(double& e) { scanf("%lf", &e); }
inline void read(char *e) { gets(e); }
inline void write(char e) { printf("%c", e); }
inline void write(int e) { printf("%d", e); }
inline void write(float e) { printf("%f", e); }
inline void write(double e) { printf("%lf", e); }
inline void write(char *e) { printf("%s",e); }
#endif // _DS_H_