广州大学学生实验报告

开课实验室:计算机科学与工程实验(电子楼418A)     2019年5月13日

学院

计算机科学与教育软件学院

年级、专业、班

计算机科学与技术172班

姓名

学号

17061

实验课程名称

数据结构实验

成绩

实验项目名称

实验二 树和二叉树的实现

指导老师

一、实验目的

理解并运用树的操作方法

二、使用仪器、器材

微机一台

操作系统:Win10

编程软件:C++

三、实验内容及原理

自己选择存储方法、自己设计输入输出方式,在实验报告中清晰说明。

  1. 输入一棵多元树,进行多种遍历

树的高度(设空树高度为-1)不小于3,包含儿子数为0、1、2、3的结点。

  1. 输入一棵二叉树进行多种遍历。

树的高度(设空树高度为-1)不小于4,包含了儿子数为0、1、2的结点。选做:二叉树的总结点(或叶片)数目的统计。

3.补充下列程序,使该程序能正确运行。

题目要求:由先序遍历序列建立二叉树的515二叉链表,中序线索化二叉树并找出结点的前驱和后继。

  • 实验过程原始数据记录

1、输入一棵多元树,进行多种遍历

树的高度(设空树高度为-1)不小于3,包含儿子数为0、1、2、3的结点。

Tree.h

#pragma once

#include <stdio.h>

#include <malloc.h>

#define MaxSize 100

typedef struct tnode

{

char data;                         //节点的值

struct tnode *hp;              //指向兄弟

struct tnode *vp;              //指向孩子节点

} TSBNode;                             //孩子兄弟链存储结构类型

TSBNode *CreateTree(char *str);         //由str建立孩子兄弟链存储结构

void DispTree(TSBNode *t);     //输出孩子兄弟链存储结构

void DestroryTree(TSBNode *&t);    //销毁树t

int TreeHeight2(TSBNode *t);

void PreOrder(TSBNode *b);     //先序遍历的递归算法

void PostOrder(TSBNode *b);        //后序遍历的递归算法

void LevelOrderTraverse(TSBNode *b);//层次遍历

tree.cpp

#include"pch.h"

#include "tree.h"

TSBNode * CreateTree(char * str)

{

struct

{

TSBNode *nodep;                //节点指针

int num;                  //孩子个数

} St[MaxSize];                     //顺序栈

int top = -1;                      //栈顶指针

int i = 0, j; char ch = str[i];

TSBNode *t = NULL, *p=NULL, *q;

while (ch != '\0')

{

switch (ch)

{

case '(': top++; St[top].nodep = p;

St[top].num = 0;               //当前节点p进栈

break;

case ')':top--;   break;            //退栈

case ',':St[top].num++; break; //栈顶节点增加一个孩子

default:

p = (TSBNode *)malloc(sizeof(TSBNode));

p->data = ch;                  //建立一个节点p存放ch

p->hp = p->vp = NULL;

if (t == NULL)                 //原为空树

t = p;

else                      //将其作为栈顶节点的一个孩子

{

if (St[top].num == 0)      //第一个孩子用vp指向它

St[top].nodep->vp = p;

else                  //其他孩子用栈顶节点的孩子节点的hp指向它

{

q = St[top].nodep->vp;

for (j = 1; j < St[top].num; j++)

q = q->hp;

q->hp = p;

}

}

break;

}

i++;

ch = str[i];

}

return t;

}

void DispTree(TSBNode * t)

{

TSBNode *p;

if (t != NULL)

{

printf("%c", t->data);

if (t->vp != NULL)        //有孩子时输出一个'('

{

printf("(");

p = t->vp;            //p指向节点t的第一个孩子

while (p != NULL)

{

DispTree(p);

p = p->hp;

if (p != NULL)

printf(",");

}

printf(")");      //输出一个')'

}

}

}

void DestroryTree(TSBNode *& t)

{

if (t != NULL)

{

DestroryTree(t->vp);

DestroryTree(t->hp);

free(t);              //释放根节点

}

}

int TreeHeight2(TSBNode * t)

{

TSBNode *p;

int h, maxh = 0;

if (t == NULL) return 0;       //空树返回0

else

{

p = t->vp;                //指向第1个孩子节点

while (p != NULL)         //扫描t的所有子树

{

h = TreeHeight2(p);   //求出p子树的高度

if (maxh < h) maxh = h;    //求所有子树的最大高度

p = p->hp;            //继续处理t的其他子树

}

return(maxh + 1);         //返回maxh+1

}

}

void PreOrder(TSBNode * b)

{

//st1为处理整个树的栈,st2为处理其兄弟节点的栈

TSBNode *st1[100], *st2[100], *p = NULL;

int top1 = -1, top2 = -1;

if (b != NULL)

{

p = b;

top1++;

st1[top1] = p;                     //先将根节点进栈

while (top1 >= 0)              //栈不空时循环

{

p = st1[top1];

top1--;                        //退栈

printf("%c ", p->data);        //打印输出

if (p->vp)                //若该节点存在兄弟节点

{

p = p->vp;

while (p != NULL)     //将兄弟节点依次进栈

{

top2++;

st2[top2] = p;

p = p->hp;

}

while (top2 >= 0)     //将兄弟节点依次退栈st2并将退栈的元素放到st1中

{

top1++;

st1[top1] = st2[top2];

top2--;

}

}

}

}

}

void PostOrder(TSBNode * b)

{

if (b == NULL)

return;

TSBNode *p = b->vp;

PostOrder(p);                               //递归打印孩子节点

if (p != NULL)

p = p->hp;

while (p)                                       //该节点不空则递归打印兄弟节点

{

PostOrder(p);

p = p->hp;

}

printf("%c ", b->data);                     //打印输出

}

}

void LevelOrderTraverse(TSBNode * b)

{

}

Main.cpp

#include "pch.h"

#include <iostream>

#include"tree.h"

int main()

{

TSBNode *t;

t = CreateTree("A(B(E,F),C(G(J)),D(H,I(K,L,M)))");

printf("t:"); DispTree(t);

printf("\n树t的高度:%d\n", TreeHeight2(t));

printf("\n树t的先根遍历结果为:"); PreOrder(t);

printf("\n");

printf("\n树t的后根遍历结果为:"); PostOrder(t);

DestroryTree(t);

return 1;

}

2、输入一棵二叉树进行多种遍历。

树的高度(设空树高度为-1)不小于4,包含了儿子数为0、1、2的结点。选做:二叉树的总结点(或叶片)数目的统计。

Btree.h

#pragma once

#include"pch.h"

#include <stdio.h>

#include <malloc.h>

#define MaxSize 100

typedef char ElemType;

typedef struct node

{

ElemType data;            //数据元素

struct node *lchild;  //指向左孩子节点

struct node *rchild;  //指向右孩子节点

} BTNode;

void CreateBTree(BTNode * &b, char *str);   //创建二叉树

void DestroyBTree(BTNode *&b);

BTNode *FindNode(BTNode *b, ElemType x);

BTNode *LchildNode(BTNode *p);

BTNode *RchildNode(BTNode *p);

int BTHeight(BTNode *b);

void DispBTree(BTNode *b);//输出二叉树

//二叉树的遍历算法

void PreOrder1(BTNode *b);//先序遍历非递归算法1

void PreOrder2(BTNode *b);//先序遍历非递归算法2

void InOrder1(BTNode *b);//中序遍历非递归算法1

void PostOrder1(BTNode *b);//后序遍历非递归算法1

//有关栈的操作

typedef struct

{

BTNode *data[MaxSize];         //存放栈中的数据元素

int top;                       //存放栈顶指针,即栈顶元素在data数组中的下标

} SqStack;                             //顺序栈类型

void InitStack(SqStack *&s);            //初始化栈

void DestroyStack(SqStack *&s);         //销毁栈

bool StackEmpty(SqStack *s);            //判断栈是否为空

bool Push(SqStack *&s, BTNode *e); //进栈

bool Pop(SqStack *&s, BTNode *&e); //出栈

bool GetTop(SqStack *s, BTNode *&e);    //取栈顶元素

Btree.cpp

#include"pch.h"

#include "btree.h"

void CreateBTree(BTNode *& b, char * str) //创建二叉树

{

BTNode *St[MaxSize], *p = NULL;

int top = -1, k, j = 0;

char ch;

b = NULL;                 //建立的二叉树初始时为空

ch = str[j];

while (ch != '\0')    //str未扫描完时循环

{

switch (ch)

{

case '(':top++; St[top] = p; k = 1; break;       //为左孩子节点

case ')':top--; break;

case ',':k = 2; break;                           //为孩子节点右节点

default:p = (BTNode *)malloc(sizeof(BTNode));

p->data = ch; p->lchild = p->rchild = NULL;

if (b == NULL)                        //*p为二叉树的根节点

b = p;

else                                   //已建立二叉树根节点

{

switch (k)

{

case 1:St[top]->lchild = p; break;

case 2:St[top]->rchild = p; break;

}

}

}

j++;

ch = str[j];

}

}

void DestroyBTree(BTNode *& b)

{

if (b != NULL)

{

DestroyBTree(b->lchild);

DestroyBTree(b->rchild);

free(b);

}

}

BTNode * FindNode(BTNode * b, ElemType x)

{

BTNode *p;

if (b == NULL)

return NULL;

else if (b->data == x)

return b;

else

{

p = FindNode(b->lchild, x);

if (p != NULL)

return p;

else

return FindNode(b->rchild, x);

}

}

BTNode * LchildNode(BTNode * p)

{

return p->lchild;

}

BTNode * RchildNode(BTNode * p)

{

return p->rchild;

}

int BTHeight(BTNode * b)

{

int lchildh, rchildh;

if (b == NULL) return(0);               //空树的高度为0

else

{

lchildh = BTHeight(b->lchild); //求左子树的高度为lchildh

rchildh = BTHeight(b->rchild); //求右子树的高度为rchildh

return (lchildh > rchildh) ? (lchildh + 1) : (rchildh + 1);

}

}

void DispBTree(BTNode * b)

{

if (b != NULL)

{

printf("%c", b->data);

if (b->lchild != NULL || b->rchild != NULL)

{

printf("(");                       //有孩子节点时才输出(

DispBTree(b->lchild);              //递归处理左子树

if (b->rchild != NULL) printf(","); //有右孩子节点时才输出,

DispBTree(b->rchild);              //递归处理右子树

printf(")");                       //有孩子节点时才输出)

}

}

}

void PreOrder1(BTNode * b)

{

BTNode *p;

SqStack *st;                   //定义一个顺序栈指针st

InitStack(st);                     //初始化栈st

Push(st, b);                   //根节点进栈

while (!StackEmpty(st))        //栈不为空时循环

{

Pop(st, p);               //退栈节点p并访问它

printf("%c ", p->data);   //访问节点p

if (p->rchild != NULL) //有右孩子时将其进栈

Push(st, p->rchild);

if (p->lchild != NULL) //有左孩子时将其进栈

Push(st, p->lchild);

}

printf("\n");

DestroyStack(st);              //销毁栈

}

void PreOrder2(BTNode * b)

{

BTNode *p;

SqStack *st;                   //定义一个顺序栈指针st

InitStack(st);                     //初始化栈st

p = b;

while (!StackEmpty(st) || p != NULL)

{

while (p != NULL)              //访问节点p及其所有左下节点并进栈

{

printf("%c ", p->data);   //访问节点p

Push(st, p);              //节点p进栈

p = p->lchild;            //移动到左孩子

}

if (!StackEmpty(st))      //若栈不空

{

Pop(st, p);               //出栈节点p

p = p->rchild;            //转向处理其右子树

}

}

printf("\n");

DestroyStack(st);              //销毁栈

}

void InOrder1(BTNode * b)

{

BTNode *p;

SqStack *st;                       //定义一个顺序栈指针st

InitStack(st);                         //初始化栈st

if (b != NULL)

{

p = b;

while (!StackEmpty(st) || p != NULL)

{

while (p != NULL)              //扫描节点p的所有左下节点并进栈

{

Push(st, p);              //节点p进栈

p = p->lchild;            //移动到左孩子

}

if (!StackEmpty(st))      //若栈不空

{

Pop(st, p);               //出栈节点p

printf("%c ", p->data);   //访问节点p

p = p->rchild;            //转向处理其右子树

}

}

printf("\n");

}

DestroyStack(st);              //销毁栈

}

void PostOrder1(BTNode * b)

{

BTNode *p, *r;

bool flag;

SqStack *st;                       //定义一个顺序栈指针st

InitStack(st);                         //初始化栈st

p = b;

do

{

while (p != NULL)                  //扫描节点p的所有左下节点并进栈

{

Push(st, p);                   //节点p进栈

p = p->lchild;                 //移动到左孩子

}

r = NULL;                              //r指向刚刚访问的节点,初始时为空

flag = true;                       //flag为真表示正在处理栈顶节点

while (!StackEmpty(st) && flag)

{

GetTop(st, p);                 //取出当前的栈顶节点p

if (p->rchild == r)            //若节点p的右孩子为空或者为刚刚访问过的节点

{

printf("%c ", p->data);   //访问节点p

Pop(st, p);

r = p;                    //r指向刚访问过的节点

}

else

{

p = p->rchild;            //转向处理其右子树

flag = false;             //表示当前不是处理栈顶节点

}

}

} while (!StackEmpty(st));         //栈不空循环

printf("\n");

DestroyStack(st);              //销毁栈

}

void InitStack(SqStack *& s)

{

s = (SqStack *)malloc(sizeof(SqStack));//分配一个是顺序栈空间,首地址存放在s中

s->top = -1;                       //栈顶指针置为-1

}

void DestroyStack(SqStack *&s)     //销毁栈

{

free(s);

}

bool StackEmpty(SqStack * s)

{

return(s->top == -1);

}

bool Push(SqStack *& s, BTNode * e)

{

if (s->top == MaxSize - 1)         //栈满的情况,即栈上溢出

return false;

s->top++;                          //栈顶指针增1

s->data[s->top] = e;               //元素e放在栈顶指针处

return true;

}

bool Pop(SqStack *& s, BTNode *& e)

{

if (s->top == -1)                  //栈为空的情况,即栈下溢出

return false;

e = s->data[s->top];               //取栈顶指针元素的元素

s->top--;                          //栈顶指针减1

return true;

}

bool GetTop(SqStack * s, BTNode *& e)

{

if (s->top == -1)                  //栈为空的情况,即栈下溢出

return false;

e = s->data[s->top];               //取栈顶元素

return true;

}

Main.cpp

int main()

{

BTNode *b;

CreateBTree(b, "A(B(D(G,H(,J)),E(,I)),C(,F))");

DispBTree(b);

printf("\n");

printf("先序遍历序列1:"); PreOrder1(b);

printf("先序遍历序列2:"); PreOrder2(b);

printf("中序遍历序列:"); InOrder1(b);

printf("后序遍历序列:"); PostOrder1(b);

DestroyBTree(b);

printf("\n");

}

3补充下列程序,使该程序能正确运行。

步骤一:新建工程,新建一个头文件,命名为 thread.h,一个源文件命名为thread.cpp

步骤二

在thread.h中编辑代码,代码如下:

#include <iostream>

using namespace std;

typedef char DataType;

typedef struct Node

{

DataType data;

int      Ltag;

int      Rtag;

__struct Node__ *LChild;   /*填空1、指针域的数据类型*/

__struct Node__ *RChild;

}BTNode;

BTNode *pre;

void CreateBiTree(BTNode  *&root, DataType Array[]) ; //创建初始化二叉树

void  Inthread(BTNode *root); //实现中序线索二叉树

BTNode * InPre(BTNode *p);  //求中序线索二叉树结点的前驱

BTNode * InNext(BTNode * p) ; //求中序线索二叉树结点的后驱

在Thread.cpp中编辑代码,代码如下:

#include "thread.h"            /*11、填空:请填空:包含头文件*/

void CreateBiTree(BTNode  *&root, DataType Array[])

{

static int count=0;      //静态变量count

char item=Array[count];//读取Array[]数组中的第count个元素

count++;

if(item == '#') //如果读入#字符,创建空树

{ root = NULL; return ;}

else

{

root = __ (BTNode *)malloc(sizeof(BTNode))__;/*填空3:生成一个新结点*/

___ root->data___ = item; /*填空4:将ch做为新结点的数据域的值*/

root->Ltag=0;

root->Rtag=0;

__ CreateBiTree(root->LChild, Array)_; /*填空5: 递归的方法,生成左子树,注意实参的表示方法*/

__ CreateBiTree(root->RChild, Array)_; /*填空6: 递归的方法,生成右子树,注意实参的表示方法*/

}

}

void  Inthread(BTNode *root)

/* 对root所指的二叉树进行中序线索化,其中pre始终指向刚访问过的结点,其初值为NULL */

{

if (root!=NULL)

{

Inthread(root->LChild);  /* 线索化左子树 */

if (root->LChild==NULL)

{

root->Ltag=___ 1__;

__ root->LChild_=pre;  /*填空7-8:置前驱线索 */

}

if (pre!=NULL&& pre->RChild==NULL)  /* 填空9-10:置后继线索 */

{

pre->Rtag=__ 1___;

__ root->RChild __=root;

}

pre=root;

Inthread(root->RChild);  /*线索化右子树*/

}

}

/* 在中序线索二叉树中查找p的中序前驱, 并用pre指针返回结果 */

BTNode * InPre(BTNode *p)

{

BTNode *q;

if(p->Ltag==1)

pre = __p->LChild__;  /*填空13:直接利用线索找前驱*/

else

{ /* 填空14-15:在p的左子树中查找"最右下端"结点 */

for(q = p->LChild;q->Rtag==__0__;q=q->_ RChild __);

pre=q;

}

return(pre);

}

/*在中序线索二叉树中查找p的中序后继结点,并用next指针返回结果*/

BTNode * InNext(BTNode * p)

{

BTNode *Next;

BTNode *q;

if (p->Rtag==1)

Next = p->RChild;  /*填空16:直接利用线索*/

else

{ /*填空17-18: 在p的右子树中查找"最左下端"结点*/

for(q=p->RChild; q->Ltag==___0___ ;q=q->__ LChild ___);

Next=q;

}

return(Next);

}

void main()

{

BTNode *root,*q;

DataType A[]="AB#CD##E##F#G##";//以"#"补充空分支后的某个遍历序列

CreateBiTree(root,A);//以先序遍历序列建立二叉树

pre = NULL;

Inthread(root);

q =InPre(root); /*找根结点的前驱,大家试找其它结点的前驱*/

cout<<root->data<<"的前驱为"<<q->data<<endl;

q =InNext(root); /*找根结点的后驱,大家试找其它结点的后驱*/

cout<<root->data<<"的后继为"<<q->data<<endl;

};

  • 实验结果及分析

1.输入一棵多元树,进行多种遍历

多元树存储结构为孩子兄弟存储结构,遍历算法:先跟遍历采用非递归算法,后根遍历采用递归算法。

2.输入一棵二叉树进行多种遍历。

遍历算法均为非递归算法

3.补充下列程序,使该程序能正确运行。

数据结构实验二 树和二叉树的实现相关推荐

  1. 数据结构-实验二  树和二叉树的实现

     广州大学学生实验报告 开课实验室:计算机科学与工程实验(电子楼417)     2018年05月16日 学院 计算机科学与教育软件学院 年级.专业.班 网络161 姓名 卟咚君 学号 1606100 ...

  2. 数据结构实验二 :二叉树的操作与实现

    数据结构实验一:线性表,堆栈和队列实现 数据结构实验二 :二叉树的操作与实现 数据结构实验三: 图的操作与实现 数据结构实验四 : 查找和排序算法实现 文章目录 一.实验目的: 二.使用仪器.器材 三 ...

  3. 2017-2018-1 20162316刘诚昊 实验二 树

    20162316刘诚昊 2017-2018-2 <Java程序设计>第二次实验 树 实验链接: 实验二 树-1-实现二叉树 实验二 树-2-中序先序序列构造二叉树 实验二 树-3-决策树 ...

  4. Python__数据结构与算法——树、二叉树(实现先、中、后序遍历)

    目录 一.树 二.二叉树 树和前面所讲的表.堆栈和队列等这些线性数据结构不同,树不是线性的.在处理较多数据时,使用线性结构较慢,而使用树结构则可以提高处理速度.不过,相对于线性的表.堆栈和队列等线性数 ...

  5. 数据结构实验三 树的遍历生成树

    广州大学学生实验报告 开课实验室:计算机科学与工程实验(电子楼418A)     2019年4月19日 学院 计算机科学与教育软件学院 年级.专业.班 计算机科学与技术 姓名 学号 实验课程名称 数据 ...

  6. 20162303 实验二 树

    北京电子科技学院(BESTI) 实 验 报 告 课程:程序设计与数据结构 班级: 1623 姓名: 石亚鑫 学号:20162303 成绩: 2分 指导教师:娄嘉鹏 王志强 实验日期:10月23日 实验 ...

  7. 【数据结构】_树与二叉树

    目录 引言 一.什么是树? 1.树的定义 2.树的特点 3.树的表示法 二.树的一些基本术语 三.树的性质 四.什么是二叉树? 1.基本概念 2.二叉树的五种基本形态 3.二叉树的性质 五.满二叉树. ...

  8. 数据结构与算法——树和二叉树***

    第五章 :树和二叉树 树和图是两种重要的非线性结构.线性结构中结点具有唯一前驱和唯一后继的关系,而非线性结构中结点之间的关系不再具有这种唯一性.其中,树形结构中结点间的关系是前驱唯一而后继不唯一,即元 ...

  9. 【数据结构Note5】- 树和二叉树(知识点超细大全-涵盖常见算法 排序二叉树 线索二叉树 平衡二叉树 哈夫曼树)

    文章目录 5.1 树和二叉树引入 5.1.1 树的概念 5.1.2 树的表示 5.1.3 树中基本术语 5.2 二叉树 5.2.1 概念 5.2.2 二叉树的性质 5.2.3 特殊的二叉树 5.2.4 ...

最新文章

  1. python中国大学排名爬虫写明详细步骤-python中国大学排名爬虫
  2. windows Pycharm 常用快捷键
  3. X-UA-Compatible 1
  4. 【若依(ruoyi)】Unknown column ‘create_time‘ in ‘order clause‘
  5. sublime php语法检查
  6. 我的AJAX 学习系列文章
  7. 微信小程序srt_微信小程序微商城(八):缓存实现商品购物车功能
  8. leetcode python3 简单题26. Remove Duplicates from Sorted Array
  9. 哈佛医学院研究员解读DeepMind大突破AlphaFold:有进步,但未解决根本问题
  10. 开启 TLS 1.3 加密协议,极速 HTTPS 体验
  11. rlocfind matlab,绘制根轨迹的MATLAB函数介绍
  12. layui 之可搜索的下拉框select lay-serach
  13. 中位数技巧(推理+证明)
  14. (转)用4年多时间, 带领微软重登全球市值第一宝座, 纳德拉是如何做到的?
  15. python画四边形_Matplotlib FigureCanvas:将四边形网格正确地绘制为轴
  16. DPDK内存管理总结
  17. 计算机科学终审多长时间,一些计算机科学核心期刊的投稿经验
  18. 爱肤宝医生产品负责人王照陆:大数据时代下的人工智能医疗
  19. 王者荣耀告诉你什么是节流
  20. Python视频分割(截取视频部分保存)

热门文章

  1. 前端学习(355):小练习
  2. 无线网络共享到CM3计算板调试时 connect: Network is unreachable
  3. Actor范围内随机生成 Learn Unreal Engine (with C++)
  4. 后来的我们王俊凯王源机器人_王俊凯杨紫到底是什么关系
  5. uniapph5授权成功后返回上一页_记一次授权系统的安全测试
  6. mysql表数据提取工具,Jailer数据提取
  7. 输入 3 个正数,判断能否构成一个三角形。
  8. [BZOJ 2654]tree(陈立杰)
  9. iOS设计模式 - 迭代器
  10. Android项目使用Eclipse进行单元测试