icoding的数据结构并没有一个测试代码,其都是直接编写一个函数的形式,因此很难知道自己的实际输出是什么。针对部分题目,我编写了一系列测试代码以供大家进行数据输出的测试。
void pre_order(BiTree root){ // todo }
请将您的函数代码复制到上述函数中,然后修改main函数的相关内容,完成测试样例的输入
注意:icoding代码以int为数据类型,我们这里以字母为数据
打印树的代码源程序来自 打印树源程序
#include<stdio.h>
#include<stdbool.h>
#include<stdlib.h>
#include<string.h>
//二叉树的创建
#define Stack_Size 50
typedef char DataType;
typedef struct Node{
DataType data;
struct Node* left;
struct Node* right;
}BiTNode, *BiTree;
typedef BiTNode* ElemType;
typedef BiTNode* P_Node;
typedef struct{
ElemType elem[Stack_Size];
int top;
}Stack;
int width,height;//打印需要用到的
void visit_node(BiTNode *node){
printf("%c ",node->data);
}
void init_stack(Stack *S) // 初始化栈
{
S->top = -1;
}
bool push(Stack* S, ElemType x) //x 入栈
{
if (S->top == Stack_Size - 1)
return false;
S->top++;
S->elem[S->top] = x;
return true;
}
bool pop(Stack* S, ElemType *px) //出栈,元素保存到px所指的单元,函数返回true,栈为空时返回 false
{
if (S->top == -1)
return false;
*px = S->elem[S->top];
S->top--;
return true;
}
bool top(Stack* S, ElemType *px) //获取栈顶元素,将其保存到px所指的单元,函数返回true,栈满时返回 false
{
if (S->top == -1)
return false;
*px = S->elem[S->top];
return true;
}
bool is_empty(Stack* S) // 栈为空时返回 true,否则返回 false
{
if (S->top == -1)
return true;
return false;
}
//创建树,将输入的字符串以先序的形式存入二叉树
BiTree _CreateByStr(char *nodes, int *i) {
//定位串处理完了
if (nodes[*i] == '\0') return NULL;
//遇到了定位串中的'.',这表明这颗子树是空树
if (nodes[*i] == '.') {
++ *i;
return NULL;
}
//生成新节点,填充数据
BiTree root = (BiTree)malloc(sizeof(BiTNode)); //生成一个新结点
//找到字母标签对应的对照表项,并赋值给data域
root->data = nodes[*i];
//每消费了一个字符,下标*i要后移
++ *i;
//递归生成子树
root->left = _CreateByStr(nodes, i); //生成左子树
root->right = _CreateByStr(nodes, i); //生成右子树
return root;
}
//求深度
int DeepTree(P_Node T)
{
if(!T)
{
return 0;
}
return DeepTree(T->left)>DeepTree(T->right)?DeepTree(T->left)+1:DeepTree(T->right)+1;
//关键代码:如果该节点的左子树深度大于右子树则将左子树的深度加一返回,这个返回值便是以该节点做根节点的树的深度,右子树深度大时则相反
}
//T为二叉树的根节点,a是数组的起始地址,i,j是当前节点在数组中的位置
//如果节点有孩子,其孩子的j坐标为 j±(height-i+1)/2
void fillArray(P_Node T,char *a,int i, int j)
{
int ti,tj;
if(T) //如果该位置有节点
{
*(a+(i*width)+j) = T->data; //向数组该点填入字符
if(T->left) //有左右孩子给对应的连接线,左右孩子的值在下一层递归赋
{
//将该点与其左孩子之间的连线全部填上'/'
for(ti=i+1,tj=j-1;tj>j-(height-i+1)/2;tj--)
{
*(a+((ti)*width)+tj) = -1;
ti++;
}
}
if(T->right)
{
for(ti=i+1,tj=j+1;tj<j+(height-i+1)/2;tj++)
{
*(a+((ti)*width)+tj) = 1;
ti++;
}
}
//经过循环,ti恰好指到其孩子所在的层
fillArray(T->left, a, ti, j-(height-i+1)/2);
fillArray(T->right, a, ti, j+(height-i+1)/2);
}
}
void printBiTree(P_Node T)
{
int i,j;
int n = DeepTree(T); //计算出深度n
//在计算机中数据以二进制形式存储,所以一个数据左移1位就相当于乘以2的1次方
width = (2<<n)-3; // 2^(n+1)-3
height = (2<<(n-1))-1; // 2^n-1
char *a = (char *)malloc(sizeof(char) * (width*height)); // 申请空间
// 空间初始化为0
for(i=0;i<height;i++)
{
for(j=0;j<width;j++)
{
*(a+(i*width)+j) = 0;
}
}
//调用之前定义好的函数,填充打印数组
fillArray(T, a, 0, (width-1)/2);
//根据打印数组的内容来实现打印
for(i=0;i<height;i++)
{
for(j=0;j<width;j++)
{
if(*(a+(i*width)+j) == -1)
{
printf("/");
}else if(*(a+(i*width)+j) == 1)
{
printf("\\");
}else if(*(a+(i*width)+j) == 0)
{
printf(" ");
}else
{
printf("%c", *(a+(i*width)+j));
}
}
printf("\n");
}
}
/以上为辅助函数
void pre_order(BiTree root){
// todo
}
void pre_order_digui(BiTree root){
if (root == NULL)
return;
visit_node(root);
pre_order_digui(root->left);
pre_order_digui(root->right);
}
int main(){
///--------以 下 内 容 可 以 修 改 ----------------
char nodes[] = "ABCD.E..F..G...";
//这是树的定位串,采用先序排列,每个节点的左右孩子用'.'分隔,空节点用'.'代替
//”.”表示空节点,即左/右孩子不存在
//这里提供了一些树的先序定位串
//1. ABC..DE..GH..F... ( 图大,不便打印)
//2. ABC...DE.F.. (图小,可以打印)
//3. ABCD....EF..G... (图小,可以打印)
//4. ABCD.E..F..G... (图大,不便打印)
//错误的使用“.”可能造成无法打印或者输出图形过于大
bool print=false;//是否打印树,默认不打印
///--------以 上 内 容 可 以 修 改 ----------------
printf("---开始测试---\n");
printf("icoding\n先序遍历\n");
printf(">>正在根据定位串生成树,若生成异常请检查定位码是否正确\n");
int i=0;//定位串起始点,请勿更改!
BiTree T = _CreateByStr(nodes, &i);
printf(">>树生成完毕\n");
if(!print) printf("\n请注意,打印树的图形过大,默认关闭树的打印功能,若需要请修改main函数的print\n");
if(print){
printf(">>打印树,树的打印代码来自于CSDN博主@冀中阿板,若侵权请联系删除\n");
printBiTree(T);
putchar('\n');
}
printf("\n>>基于递归先序遍历(正确的遍历结果)\n");
pre_order_digui(T);
printf("\n>>基于栈先序遍历(您的代码的遍历结果)\n");
pre_order(T);
printf("\n\n若打印为空请检查是否用到了visit_node()函数");
printf("\n\n本程序仅供输出结果,不判断结果的正确性");
printf("\n---测试结束---\n");
return 0;
}
若不对main函数的内容进行改动,那么输出的结果将是
你可以自行修改main函数的print的值来实现打印图的功能。