title: 依据广度优先的输入字符串 生成二叉树
date: 2020-12-26 11:18:34
tags: 二叉树
categories: 数据结构
说明
这个根据输入的字符串自动生成一个二叉树
使用的思想是广搜(BFS)
要用到队列生成二叉树
举个例子
输入 12634^7^^^58^^^^^
生成的二叉树为:
1
/ \
2 6
/ \ / \
3 4 ^ 7
/ \ / \ / \
^ ^ ^ 5 8 ^
/ \ / \
^ ^ ^ ^
你可能会疑惑这个二叉树和平时的不一样,
其实这才是计算机眼中的二叉树,
只是平时见到的把NULL省略掉了
既然我们是学代码的,我们的脑回路就应该和计算机一样
难道不是么? (手动滑稽)
收获
写这个算法的时候,get到一个新的点就是:
我可以传结构体变量中的成员变量的地址给函数,而不是直接传一个结构体地址
这样的话,可以具体到结构体中的某个域来进行修改
比如说 左右子树,当你这个函数希望有的时候修改的是存左子树地址的指针域,有的时候修改存右子树地址的指针域时,如果你直接传一个结构体地址过去,除非有标志位或者标志变量,否则是不知道该做什么操作的,这时候你只需要在调用的时候,直接传节点中存左子树地址的指针的地址或者传节点中存右子树地址的指针的地址就行,而不用再去设置标志判断了。
详情请见本代码中为一个节点的左右指针域赋值的操作
代码附上
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXSIZE 100
typedef struct treeNode
{
char data;
struct treeNode *left, *right;
} TreeNode, *Tree;
typedef struct queue
{
Tree arr[MAXSIZE];
int tail;
int head;
} * Queue;
Queue newQueue();
// 入队的元素是节点的地址
void inQueue(Queue, Tree);
// 出队的是节点的地址
Tree outQueue(Queue);
char *getStr();
Tree creTree(char *, Queue);
// 传一个队列,树节点的二级指针, 字符串,当前字符的索引位置
void creTree2(Tree *, Queue, char *, int *);
void preOrder(Tree);
int main(void)
{
// 得到了一个空队列的地址
Queue queue = newQueue();
// 得到用户输入的字符串
char *str = getStr();
printf("%s\n", str);
printf("%d\n", strlen(str));
// 根据用户输入的字符串生成二叉树
Tree tree = creTree(str, queue);
preOrder(tree);
return 0;
}
void preOrder(Tree tree)
{
if (tree == NULL)
return;
printf("%c\n", tree->data);
preOrder(tree->left);
preOrder(tree->right);
}
void creTree2(Tree *ppChild, Queue queue, char *str, int *strIndex)
{
if (*strIndex < strlen(str))
{
Tree p;
if (str[*strIndex] == '^')
p = NULL;
else
{
p = (Tree)malloc(sizeof(TreeNode));
p->data = str[*strIndex];
inQueue(queue, p);
}
(*strIndex)++;
*ppChild = p;
}
}
Tree creTree(char *str, Queue queue)
{
int nodeCounts = strlen(str);
int strIndex = 0;
Tree p = (Tree)malloc(sizeof(TreeNode));
p->data = str[strIndex];
strIndex++;
inQueue(queue, p);
// 头指针
Tree tree = p;
while (strIndex < nodeCounts)
{
Tree temp = outQueue(queue);
// 队列的地址, 当前下标, 字符数组
// 树节点的二级指针
creTree2(&(temp->left), queue, str, &strIndex);
creTree2(&(temp->right), queue, str, &strIndex);
}
return tree;
}
// 接收用户输入的一串字符
char *getStr()
{
char *p = (char *)malloc(sizeof(char) * MAXSIZE);
scanf("%s", p);
return p;
}
// 创建并初始化一个队列出来
Queue newQueue()
{
Queue list = (Queue)malloc(sizeof(struct queue));
list->head = 0;
list->tail = 0;
return list;
}
// 循环入队
void inQueue(Queue queue, Tree p)
{
if ((queue->tail + 1) % MAXSIZE == queue->head)
{
printf("队满, 入队失败\n");
return;
}
queue->arr[queue->tail] = p;
queue->tail = (queue->tail + 1) % MAXSIZE;
}
// 循环出队
Tree outQueue(Queue queue)
{
if (queue->tail == queue->head)
{
printf("队空, 出队失败\n");
return NULL;
}
Tree temp = queue->arr[queue->head];
queue->head = (queue->head + 1) % MAXSIZE;
return temp;
}