实验八 二叉树的构造和遍历
1、实验目的:
(1)理解二叉树的二叉链表存储。
(2)理解二叉树这种递归数据结构以及其操作的递归实现。
2、实验环境与设备:
已安装Visual Studio 2010(或其以上版本)集成开发环境的计算机。
3、实验原理:
(1)二叉树的二叉链表存储。
(2)二叉树的三种遍历算法。
4、实验内容:
(1)基于标明空子树的先序遍历序列构造一棵采用二叉链表存储的二叉树。(空子树用“#”表示,如某棵二叉树的标明空子树的先序遍历序列为:ABC##DE#G##F###)
(2)设计递归算法分别对该二叉树做先序、中序、后序遍历,要求输出这三种遍历序列。
5、实验考核:
(1)完成纸质版实验报告
(2)提交电子版作业
6、执行结果示例如下:
上述二叉树如下图所示。
#include <stdio.h>
#include "stdlib.h"
#define STACK_INIT_SIZE 10 //栈的初始长度
#define STACKINCREMENT 5 //栈的追加长度
typedef struct bitree{
char data;
struct bitree *lchild, *rchild;
}bitree; //二叉树结点定义
typedef struct {
bitree **base;
bitree **top;
int stacksize;
}sqstack; // 链栈结点定义top栈顶 base栈底 且栈元素是指向二叉树结点的二级指针
//建立一个空栈
int initstack(sqstack *s)
{
s->base = (bitree *)malloc(STACK_INIT_SIZE*sizeof(bitree)); //栈底指向开辟空间
if (!s->base) exit(1); //抛出异常
s->top = s->base; //栈顶=栈尾 表示栈空
s->stacksize = STACK_INIT_SIZE; //栈长度为开辟空间大小
return 1;
}
//进栈
int push(sqstack *s, bitree *e)
{
if (s->top - s->base >= s->stacksize) //如果栈满 追加开辟空间
{
s->base = (bitree *)realloc(s->base, (s->stacksize + STACKINCREMENT)* sizeof(bitree));
if (!s->base) exit(1); //抛出异常
s->top = s->base + s->stacksize; //感觉这一句没用
s->stacksize += STACKINCREMENT;
}
*(s->top) = e; s->top++; //进栈 栈顶后移
return 1;
}
//出栈
int pop(sqstack *s, bitree **e)
{
if (s->top == s->base) return 0; //栈空 返回0
--s->top; *e = *(s->top); //栈顶前移 取出栈顶元素给e
return 1;
}
//取栈顶
int gettop(sqstack *s, bitree **e) //去栈顶元素 注意top指向的是栈顶的后一个
{
if (s->top == s->base) return 0; //所以 s->top-1
*e = *(s->top - 1);
return 1;
}
/*------------------------非递归-----先序建立二叉树----------------------------------*/
bitree *createprebitree()
{
char ch; bitree *ht, *p, *q;
sqstack *s;
s = malloc(sizeof(bitree)); //加上这一句为s 初始化开辟空间
ch = getchar();
if (ch != '#'&&ch != '\n') /* 输入二叉树先序顺序 是以完全二叉树的先序顺序
不是完全二叉树的把没有的结点以#表示 */
{
ht = (bitree *)malloc(sizeof(bitree));
ht->data = ch;
ht->lchild = ht->rchild = NULL;
p = ht;
initstack(s);
push(s, ht); //根节点进栈
while ((ch = getchar()) != '\n') // 算
{
if (ch != '#') {
q = (bitree *)malloc(sizeof(bitree)); // 法
q->data = ch; //
if (p == *(s->top - 1)) p->lchild = q; // 核
else p->rchild = q; //
push(s, q); p = q; // 心
} //
else {
if (p == *(s->top - 1)) p->lchild = NULL; // 的
else p->rchild = NULL; //
pop(s, &p);
} // 步
//
} // 骤
return ht;
}
else return NULL;
}
/*--------------------------递归---------先序建立二叉树-------------------------------*/
void CreateBiTree(bitree **T) {
//按先序次序输入二叉树中的结点的值(一个字符),空格字符表示空树,
//构造二叉链表表示二叉树
char ch;
scanf_s("%c", &ch);
if (ch == '#') *T = NULL;
else{
*T = (bitree *)malloc(sizeof(bitree));
if (!*T) exit(1);
(*T)->data = ch; //生成根结点
CreateBiTree(&(*T)->lchild); //构造左子树
CreateBiTree(&(*T)->rchild); //构造右子树
}
}
/*--------------------------非递归-------中序建立二叉树-------------------------------*/
/*--------------------------递归---------中序建立二叉树-------------------------------*/
/*--------------------------非递归-------后序建立二叉树-------------------------------*/
/*--------------------------递归---------后序建立二叉树-------------------------------*/
/*-----------------------非递归------先序输出二叉树------------------------------*/
void preordertraverse(bitree *h)
{
sqstack m;
initstack(&m);
while (h || m.base != m.top)
{
if (h) { push(&m, h); printf("%c", h->data); h = h->lchild; }
else{
pop(&m, &h);
h = h->rchild;
}
}
}
/*------------------------非递归-----中序输出二叉树----------------------------*/
void inordertraverse(bitree *h)
{
sqstack m;
initstack(&m);
while (h || m.base != m.top)
{
if (h) { push(&m, h); h = h->lchild; }
else {
pop(&m, &h);
printf("%c", h->data);
h = h->rchild;
}
}
}
/*---------------------非递归----后序遍历二叉树----------------------------------*/
void postordertraverse(bitree *h)
{
sqstack m;
bitree *r = h; //使用r结点表示访问了右子树 代替标志域
initstack(&m);
while (h || m.base != m.top)
{
if (h) {
push(&m, h);
h = h->lchild;
}
else {
gettop(&m, &h);
if (h->rchild&&h->rchild != r)
{
h = h->rchild;
push(&m, h);
h = h->lchild;
}
else{
pop(&m, &h);
printf("%c", h->data);
r = h; h = NULL;
}
}
}
}
//层次遍历二叉树 用队列 哈哈以后做
/*-------------------------------主过程-------------------------------*/
int main()
{
bitree *ht;
//printf("先序非递归建立一个二叉树:");
printf("以标明空子树的先序遍历序列构造二叉树:\n");
if ((ht = createprebitree()) != NULL) //非递归建立
//CreateBiTree(&ht);
//if(ht!=NULL) //递归建立
{
printf("先序遍历输出二叉树:");
preordertraverse(ht);
putchar('\n');
printf("中序遍历输出二叉树:");
inordertraverse(ht);
putchar('\n');
printf("后序遍历输出二叉树:");
postordertraverse(ht);
putchar('\n');
}
else printf("空二叉树\n");
system("pause");
return 0;
}