打印二叉树结构(设计性实验)

打印二叉树结构(设计性实验)

1. 需求分析

按凹入表形式横向打印二叉树结构,即二叉树的根在屏幕的左边,二叉树的左子树在屏幕的下边,二叉树的右子树在屏幕的上边。例如:测试数据由读者依据软件工程的测试技术自己确定。注意测试边界数据,如空二叉树。
在这里插入图片描述

实现提示
(1) 利用中序遍历方法。
(2) 利用结点的深度控制横向位置。

2. 概要设计

  1. 为了实现程序功能,需要定义树的抽象数据类型。
ADT BinaryTree{
    数据对象D:D是具有相同特性的数据元素的集合
    数据关系R:
      若D = Φ,则R = Φ,称BinaryTree为空二叉树
      若D ≠ Φ,则R = {H},H有如下二元关系:
        (1)在D中存在唯一的称为根的数据元素root,它在关系H下无前驱;
        (2)若D-{root} ≠ Φ,则存在D - {root} = {Dl,Dr},且Dl ∩ Dr = Φ;
        (3)若Dl ≠ Φ,则Dl中存在唯一的元素xl,<root,xl>∈H,且存在Dl上的关系Hl⊂H;
            若Dr ≠ Φ,则Dr中存在唯一的元素xr,<root,xr>∈H,且存在Dr上的关系Hr⊂H;
            H = {<root,xl><root,xr>,Hl,Hr};
        (4(Dl,{Hl})是一棵符合本定义的二叉树,称为根的左子树,
             (Dr,{Hr})是一棵符合本定义的二叉树,称为根的右子树;

    typedef struct BiTNode{
	elemtype data;
	int deep;
	struct BiTNode *lchild;
	struct BiTNode *rchild;
}*bitree,bitnode;                 //树结构 

    基本操作P:
     InitBiTree(&T);
        操作结果:构造空的二叉树T。
     DestoryBiTree(&T);
        初始条件:二叉树T存在。
        操作结构:销毁二叉树T。
     CreateBiTree(&T,definition);
        初始条件:definition给出二叉树T的定义。
        操作结果:按definition构造二叉树T。
     ClearBiTree(&T);
        初始条件:二叉树T存在。
        操作结果:将二叉树清为空树。
     BiTreeEmpty(T);
        初始条件:二叉树T存在。
        操作结果:若T为空二叉树,返回TRUE,否则返回FALSE。
     BiTreeDepth(T);
        初始条件:二叉树T存在。
        操作结果:返回T的深度。
     Root(T);
        初始条件:二叉树T的根存在。
        操作结果:返回T的根。
     Value(T,e);
        初始条件:二叉树T存在,e是T中某个结点。
        操作结果:返回e的值。
     Assign(T,&e,value);
        初始条件:二叉树T存在,e是T中的某个结点。
        操作结果:结点e赋值为value。
     Parent(T,e);
        初始条件:二叉树T存在,e是T中的结点。
        操作结果:若e是T的非根结点,则返回它的双亲,否则返回"空"LeftChild(T,e);
        初始条件:二叉树T存在,e是T中的某个结点。
        操作结果:返回e的左孩子。若e无左孩子,则返回"空"RightChild(T,e);
        初始条件:二叉树T存在,e是T中的某个结点。
        操作结果:返回e的右孩子。若e无右孩子,则返回"空"LeftSibling(T,e);
        初始条件:二叉树T存在,e是T中的某个结点。
        操作结果:返回e的左兄弟。若e是T的左孩子或无左兄弟,则返回"空"RightSibling(T,e);
        初始条件:二叉树T存在,e是T中的某个结点。
        操作结果:返回e的右兄弟。若e是T的右孩子或无右兄弟,则返回"空"InsertChild(T,p,LR,c);
        初始条件:二叉树T存在,p指向T中的某个结点,LR为01,非空二叉树c与T不想交且右子树为空。
        操作结果:根据LR为01,插入c为T中p所指结点的左或右子树。p所指结点的原有左或右子树则成为c的右子树。
     DeleteChile(T,p,LR);
        初始条件:二叉树T存在,p指向T中的某个结点,LR为01.
        操作结果:根据LR为01,删除T中p所指结点的左或右子树。
     PreOrderTraverse(T,visit());
        初始条件:二叉树T存在,visit()是对结点操作的应用函数。
        操作结果:先序遍历T,对每个结点调用函数visit一次且仅一次。一旦visit失败,则操作失败。
     InOrderTraverse(T,visit());
        初始条件:二叉树T存在,visit()是对结点操作的应用函数。
        操作结果:中序遍历T,对每个结点调用函数visit一次且仅一次。一旦visit失败,则操作失败。
     PostOrderTraverse(T,visit());
        初始条件:二叉树T存在,visit()是对结点操作的应用函数。
        操作结果:后序遍历T,对每个结点调用函数visit一次且仅一次。一旦visit失败,则操作失败。
     LevelOrderTraverse(T,visit());
        初始条件:二叉树T存在,visit()是对结点操作的应用函数。
        操作结果:层序遍历T,对每个结点调用函数visit一次仅且一次。一旦visit失败,则操作失败。
}ADT BinaryTree

3.具体代码

  • 二叉树的建立与遍历.h:
#include<stdio.h>
#include<stdlib.h>

#define elemtype char
#define OK 1
#define ERROR 0

typedef struct BiTNode{//二叉树 
	elemtype data;//数据 
	int deep;//深度 
	struct BiTNode *lchild;//左子树 
	struct BiTNode *rchild;//右子树 
}*bitree,bitnode;                 //树结构 
 
int createbitree(bitree *t,FILE *r,int n)    //建树 
{
    char ch;//字符 
    if(fscanf(r,"%c",&ch) != EOF)//从文件中读取字符 
    {
    	if(ch == '\n')//如果换行 
    	{
    		
    		return OK;//则返回 
		}
    	if(ch == ' ')//如果读取为空格 
    	{
    		(*t) = NULL;//则节点为空 
    		return OK;
		}
		else//递归调用建立二叉树 
		{
			(*t) = (bitree)malloc(sizeof(bitnode));//先对本节点创建空间 
			(*t)->data = ch;//数据 
			(*t)->deep = n+1;//深度,从1开始,不断往下加 
			createbitree(&((*t)->lchild),r,n+1);//对左子树开始递归 
			createbitree(&((*t)->rchild),r,n+1);//对右子树开始递归 
		}
	    return OK;
	}
	return ERROR;	
}

void inorder(bitnode *t,void (*visit)(bitree t,FILE *w),FILE *w)   //中序遍历 
{
	if(t == NULL)
	{
		return;
	}
	inorder(t->rchild,visit,w);//先打印右边的节点(因为在上方) 
	visit(t,w);//再中间节点 
	inorder(t->lchild,visit,w);//再左边节点 
} 

  • 打印二叉树结构.c:
#include<stdio.h>
#include<stdlib.h>
#include"二叉树的建立与遍历.h" 

void visit(bitree t,FILE *w)         //打印二叉树 
{
	int i = 0;
	for(;i < t->deep;i++)//按深度遍历 
	{
		fprintf(w,"              ");//深度越长,打印的空格越多 (深度反映在水平方向) 
	}
	fprintf(w,"%c",t->data);//把数据打印 
	fprintf(w,"\n\n\n");//空行 
}

int main()
{
	FILE *r,*w;//文件读写指针 
	printf("请将文件放在'二叉树数据.txt'中(放好按ENTER键继续):");
	getchar();
	if((r = fopen("二叉树数据.txt","rt")) == NULL)
	{
		exit(ERROR);
	}
	if((w = fopen("二叉树.txt","w")) == NULL)
	{
        printf("\n无法创建二叉树遍历结果.txt”!");
        exit(ERROR);
    }
    int o=1;
    for(;;o++)//循环 
    {
	    bitree t;//建立二叉树 
        if(createbitree(&t,r,0) == 0)//无法建立二叉树,退出循环 
        {
        	break;
		}
		if(createbitree(&t,r,0) == 1)//可以建立二叉树,就直接中序遍历输出 
        {
        	fprintf(w,"第%d个二叉树:\n\n\n",o); 
        	inorder(t,visit,w);
            fprintf(w,"\n\n\n"); 
		}
	}
    fclose(w);
    printf("结果已生成在'二叉树.txt'中。"); 
    return 0;
}
  • 4
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我来回答您的问题。 首先,按入表形式横向打印二叉树结构是一种常用的二叉树可视化方式,可以直观地展示二叉树结构。具体实现过程如下: 1. 定义一个结构体Node表示二叉树的节点,包含数据域和指向左右子节点的指针。 2. 定义一个函数printTree以根节点和层数为参数,用于打印二叉树结构。 3. 在printTree函数中,先判断根节点是否为空,如果为空则直接返回。 4. 如果根节点不为空,则打印根节点的数据域,并将当前层数加1。 5. 递归调用printTree函数,传入左子节点和当前层数,用于打印左子树。 6. 递归调用printTree函数,传入右子节点和当前层数,用于打印右子树。 7. 在打印左右子树之前,需要根据当前层数计算出缩进量,并将缩进量作为第一个参数传入printTree函数,用于控制打印格式。 8. 在打印左右子树之后,需要将当前层数减1,以便于回溯到上一层继续打印。 下面是该算法的代码实现: ``` typedef struct Node { int data; struct Node* left; struct Node* right; } Node; void printTree(int indent, int level, Node* root) { if (root != NULL) { int i; for (i = 0; i < indent; i++) { printf(" "); } printf("%d\n", root->data); printTree(indent + 4, level + 1, root->left); printTree(indent + 4, level + 1, root->right); } } ``` 在调试该算法时,可以采用以下步骤: 1. 编写测试用例,包括多种不同的二叉树结构,例如完全二叉树、满二叉树、非完全二叉树等。 2. 运行程序,检查输出结果是否符合预期,特别要注意缩进量是否正确。 3. 如果输出结果不符合预期,可以在printTree函数中加入调试语句,例如打印当前层数、缩进量等,以便于定位问题所在。 4. 如果仍然无法定位问题,可以使用调试工具,例如GDB或Visual Studio Debugger,逐步调试程序,查看变量的值是否正确,以便于找到问题所在。 总之,按入表形式横向打印二叉树结构是一种常用的二叉树可视化方式,可以直观地展示二叉树结构。在调试该算法时,需要注意输出格式和缩进量的正确,以及使用调试工具辅助定位问题

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值