由完全二叉树数组构建树
1. 通过递归思想实现。
设完全二叉树的数组表示为:['A', 'B', 'c', 'D', '#', '#', 'E'];则可以看出下标为 i 的元素的左右子树分别为 2*i+1,2*i+2。及 ;'A' 的左子树为 'B',右子树为 'C'。
故代码实现:
void createTree(Tree **root, int i, int *tree, int length)
{
if(tree[i] == '#' || i >= length)
return;
*root = (Tree *)malloc(sizeof(Tree));
(*root)->data = tree[i];
createTree((*root)->leftTree, 2*i+1, tree, n);
createTree((*root)=>rightTree, 2*i+2, tree, n);
}
// 代码分析
// 1. 参数:root 为根节点,i 为数组下标,tree 为数组, n 为 数组长度
// 2. 根节点需要为根节点地址的地址,由于地址为引用类型,若参数只是为跟结点的地址,
// 每次调用时的地址都是同一个,这会让根节点里的信息随着调用而改变。而传进地址的地址,
// 则会随着每次调用而改变地址。这正是我们想要的,根据不同的地址存储不同的根节点。
整体代码如下:
#include<stdio.h>
#include<stdlib.h>
// 定义完全二叉树数组
char tree[30] = "ABCD##E#F####GH";
// 定义长度
int length = 15;
typedef struct TREE{
char data;
struct TREE *leftTree;
struct TREE *rightTree;
}Tree;
Tree * createNode(); // 创建结点
void createTree(Tree **, int, char *); // 创建二叉树
void prePrintTree(Tree *); // 前序打印二叉树
void midPrintTree(Tree *); // 中序打印二叉树
int main()
{
Tree *head = NULL;
createTree(&head, 0, tree);
prePrintTree(head);
printf("\n");
midPrintTree(head);
printf("\n");
}
Tree * createNode()
{
Tree *root = (Tree *)malloc(sizeof(tree));
root->leftTree = NULL;
root->rightTree = NULL;
return root;
}
// 创建二叉树
void createTree(Tree **root, int i, char * tree)
{
if(i > length-1 || tree[i] == '#')
return ;
*root = createNode();
(*root)->data = tree[i];
createTree(&((*root)->leftTree), 2*i+1, tree);
createTree(&((*root)->rightTree), 2*i+2, tree);
}
// 前序打印
void prePrintTree(Tree *root)
{
if(root == NULL)
return ;
printf("%c ", root->data);
prePrintTree(root->leftTree);
prePrintTree(root->rightTree);
}
// 中序打印
void midPrintTree(Tree *root)
{
if(root == NULL)
return;
midPrintTree(root->leftTree);
printf("%c ", root->data);
midPrintTree(root->rightTree);
}
2. 通过队列实现
设完全二叉树为['A', 'B', 'C', 'D', '#', '#', 'E'],我们可以通过一层一层的创建树,且创建的顺序和数组的顺序一样。
实现思路:
- 创建一个队列,其有特性:队头出队,队尾入队。
- 现将头结点入队,然后标记现有队列的元素个数。
- 循环现有个数:出队,将其数据值等于数组相应的元素值。然后将其左右结点入队。
- 由于队列是先进先出,且每次循环前有标记现有的个数,故每次出队都是旧数据(这一层的结点),对于新进的数据(下一层的结点)则由下次循环是遍历。
代码实现:
int i = 0, j;
Tree *head = NULL; // 声明树首节点
Tree **root;
// 创建循环队列
Stack *stack = (Stack *)malloc(sizeof(Stack));
stack->head = 0;
stack->foot = 0;
stackPush(stack, &head); // 先将首节点入栈
while(i < length) // 遍历数组,遍历完时,树生成完成
{
j = (stack->foot - stack->head + 20)%20; // 记录当前队列的数量,这个队列是循环队列
for(j; j>0; j--){ // 遍历旧的队列元素并出队
root = stackPop(stack);
*root = createNode();
(*root)->data = tree[i]; // 结点的数据值等于数组的元素值
i++; // 数组下标加1
stackPush(stack, &((*root)->leftTree)); // 将结点的左右子树入队
stackPush(stack, &((*root)->rightTree));
}
}
整体代码如下:
#include<stdio.h>
#include<stdlib.h>
char tree[30] = "ABCD##E#F####GH"; // 定义完全二叉树和数组
int length = 15; // 数组长度
typedef struct TREE{ // 定义树结点
char data;
struct TREE *leftTree;
struct TREE *rightTree;
}Tree;
typedef struct STACK{ // 定义队列
Tree **array[20];
int head;
int foot;
}Stack;
Tree * createNode(); // 创建树节点
void stackPush(Stack *stack, Tree **); // 入队操作(循环队列)
Tree **stackPop(Stack *stack); // 出队操作
void prePrintTree(Tree *); // 前序输出
int main()
{
int i = 0, j;
Tree *head = NULL; // 定义头结点
Tree **root;
// 创建循环队列
Stack *stack = (Stack *)malloc(sizeof(Stack));
stack->head = 0;
stack->foot = 0;
stackPush(stack, &head); // 将头结点入队
while(i < length)
{
j = (stack->foot - stack->head + 20)%20;
printf("%d\n", j);
for(j; j>0; j--){
root = stackPop(stack);
*root = createNode();
(*root)->data = tree[i];
printf("%c", (*root)->data, (*root)->leftTree);
i++;
//(*root)->leftTree = createNode();
//(*root)->rightTree = createNode();
stackPush(stack, &((*root)->leftTree));
stackPush(stack, &((*root)->rightTree));
}
}
printf("\n");
prePrintTree(head);
}
Tree * createNode()
{
Tree *root = (Tree *)malloc(sizeof(tree));
root->leftTree = NULL;
root->rightTree = NULL;
return root;
}
// 进队列
void stackPush(Stack *stack, Tree **root)
{
if(stack->foot == stack->head-1){
printf("队满");
return;
}
if(stack->foot < 19){
stack->array[stack->foot] = root;
stack->foot ++;
}
else{
stack->array[stack->foot] = root;
stack->foot = 0;
}
}
// 出队列
Tree **stackPop(Stack *stack)
{
Tree **root;
if(stack->foot == stack->head){
printf("队空");
return NULL;
}
if(stack->head < 20){
root = stack->array[stack->head];
stack->head ++;
}
else{
root = stack->array[stack->head];
stack->head = 0;
}
return root;
}
void prePrintTree(Tree *root)
{
if(root == NULL)
return ;
if(root->data != '#')
printf("%c ", root->data);
prePrintTree(root->leftTree);
prePrintTree(root->rightTree);
}