注:只给出C语言实现代码,涉及到的数据结构相关概念请自行阅读相关书籍或参考其他博文;
本文代码功能:给定整数建立二叉排序树,以广义表形式打印建树过程。建树完成后输出前中后序版。额外增加调试版帮助理解递归插入过程。
①版本1(建树,广义表打印,前中后序)
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
/*建立一个排序二叉树(二叉查找树)
*以广义表形式打印树结构
*/
typedef struct Node {
int data;//树节点数据域存整数
struct Node *lchild, *rchild;
} Node;
typedef struct Tree {
Node *root;
int length;//总结点数
} Tree;
Node *init_node(int val) {
Node *p = (Node *)malloc(sizeof(Node));
p->data = val;
p->lchild = p->rchild = NULL;
return p;
}
void clear_node(Node *node) {
if (node == NULL) return ;
clear_node(node->lchild);
clear_node(node->rchild);
free(node);
return ;
}
Tree *init_tree() {
Tree *t = (Tree *)malloc(sizeof(Tree));
t->root = NULL;
t->length = 0;
return t;
}
void clear_tree(Tree *tree) {
if (tree == NULL) return ;
clear_node(tree->root);
free(tree);
return ;
}
Node *insert_node(Node *, int, int *);
void insert(Tree *tree, int val) {
//二叉排序树插入方式插入
if (tree == NULL) return ;
int flag = 0;
tree->root = insert_node(tree->root, val, &flag);
tree->length += flag;
return ;
}
Node *insert_node(Node *root, int val, int *flag) {
if (root == NULL) {
//条件成立则一定插入成功
*flag = 1; //加入falg判断插入是否成功,原来就有的节点就不能插入
return init_node(val);
}
if (root->data == val) return root; //原来就有的节点就不能插入
if (root->data > val) root->lchild = insert_node(root->lchild, val, flag);
else root->rchild = insert_node(root->rchild, val, flag);
return root;
}
void pre_order_node(Node *);
void pre_order(Tree *tree) {
//前序遍历
if (tree == NULL) return ;
printf("pre_order :");
pre_order_node(tree->root); //封装一个方法 打印节点
printf("\n");
return ;
}
void pre_order_node(Node *root) {
if (root == NULL) return ;
printf("%2d ", root->data);
pre_order_node(root->lchild); //递归打印左子树值
pre_order_node(root->rchild); //递归打印右子树值
return ;
}
void in_order_node(Node *);
void in_order(Tree *tree) {
if (tree == NULL) return ;
printf("in_order :");
in_order_node(tree->root);
printf("\n");
return ;
}
void in_order_node(Node *root) {
if (root == NULL) return ;
in_order_node(root->lchild); //递归打印左子树值
printf("%2d ", root->data);
in_order_node(root->rchild); //递归打印右子树值
return ;
}
void post_order_node(Node *);
void post_order(Tree *tree) {
if (tree == NULL) return ;
printf("post_order:");
post_order_node(tree->root);
printf("\n");
return ;
}
void post_order_node(Node *root) {
if (root == NULL) return ;
post_order_node(root->lchild); //递归打印左子树值
post_order_node(root->rchild); //递归打印右子树值
printf("%2d ", root->data);
return ;
}
void output_node(Node *);
void output(Tree *tree) {
if (tree == NULL) return ;
printf("tree(%2d):", tree->length);
output_node(tree->root);
printf("\n");
return ;
}
void output_node(Node *root) {
//以广义表形式打印树结构
if (root == NULL) return ;
printf("%d", root->data);
if (root->lchild == NULL && root->rchild == NULL) return ;
printf("(");
output_node(root->lchild);
printf(",");
output_node(root->rchild);
printf(")");
return ;
}
int main() {
srand(time(0));
Tree *tree = init_tree();
#define MAX_OP 10
for (int i = 0; i < MAX_OP; i++) {
int val = rand() % 100;
insert(tree, val);
output(tree);
}
pre_order(tree);
in_order(tree);
post_order(tree);
#undef MAX_OP
clear_tree(tree);
return 0;
}
②版本2(调试版,帮助理解递归插入过程)
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
/*建立一个排序二叉树(二叉查找树)
*以广义表形式打印树结构
*/
#define GREEN(a) "\033[32m" a "\033[0m\n"
#define Blue(a) "\033[34m" a "\033[0m"
typedef struct Node {
int data;//树节点数据域存整数
struct Node *lchild, *rchild;
} Node;
typedef struct Tree {
Node *root;
int length;//总结点数
} Tree;
Node *init_node(int val) {
Node *p = (Node *)malloc(sizeof(Node));
p->data = val;
p->lchild = p->rchild = NULL;
return p;
}
void clear_node(Node *node) {
if (node == NULL) return ;
clear_node(node->lchild);
clear_node(node->rchild);
free(node);
return ;
}
Tree *init_tree() {
Tree *t = (Tree *)malloc(sizeof(Tree));
t->root = NULL;
t->length = 0;
return t;
}
void clear_tree(Tree *tree) {
if (tree == NULL) return ;
clear_node(tree->root);
free(tree);
return ;
}
Node *insert_node(Node *, int, int *, int *);
void insert(Tree *tree, int val) {
//二叉排序树插入方式插入
if (tree == NULL) return ;
int flag = 0, count = 0;;
tree->root = insert_node(tree->root, val, &flag, &count);
tree->length += flag;
return ;
}
Node *insert_node(Node *root, int val, int *flag, int *count) {
if (root == NULL) {
//条件成立则一定插入成功
*flag = 1; //加入falg判断插入是否成功,原来就有的节点就不能插入
printf(GREEN("root count = %d"), (*count)++);
return init_node(val);
}
if (root->data == val) return root; //原来就有的节点就不能插入
//printf("pre:root->left or right count = %d\n", (*count)++);
if (root->data > val) {
printf(Blue("left in count = %d\n"), (*count)++);
root->lchild = insert_node(root->lchild, val, flag, count);
printf("left out count = %d\n", (*count)++);
}
else {
printf(Blue("right in count = %d\n"), (*count)++);
root->rchild = insert_node(root->rchild, val, flag, count);
printf("right out count = %d\n", (*count)++);
}
printf("post: over count = %d\n", (*count)++);
return root;
}
/*
void pre_order_node(Node *);
void pre_order(Tree *tree) {//前序遍历
if (tree == NULL) return ;
printf("pre_order :");
pre_order_node(tree->root); //封装一个方法 打印节点
printf("\n");
return ;
}*/
void pre_order_node(Node *root) {
if (root == NULL) return ;
printf("%2d ", root->data);
pre_order_node(root->lchild); //递归打印左子树值
pre_order_node(root->rchild); //递归打印右子树值
return ;
}
/*
void in_order_node(Node *);
void in_order(Tree *tree) {
if (tree == NULL) return ;
printf("in_order :");
in_order_node(tree->root);
printf("\n");
return ;
}*/
void in_order_node(Node *root) {
if (root == NULL) return ;
in_order_node(root->lchild); //递归打印左子树值
printf("%2d ", root->data);
in_order_node(root->rchild); //递归打印右子树值
return ;
}
/*void post_order_node(Node *);
void post_order(Tree *tree) {
if (tree == NULL) return ;
printf("post_order:");
post_order_node(tree->root);
printf("\n");
return ;
}*/
void post_order_node(Node *root) {
if (root == NULL) return ;
post_order_node(root->lchild); //递归打印左子树值
post_order_node(root->rchild); //递归打印右子树值
printf("%2d ", root->data);
return ;
}
/*void output_node(Node *);
void output(Tree *tree) {
if (tree == NULL) return ;
printf("tree(%2d):", tree->length);
output_node(tree->root);
printf("\n");
return ;
}*/
void output_node(Node *root) {
//以广义表形式打印树结构
if (root == NULL) return ;
printf("%d", root->data);
if (root->lchild == NULL && root->rchild == NULL) return ;
printf("(");
output_node(root->lchild);
printf(",");
output_node(root->rchild);
printf(")");
return ;
}
int main() {
srand(time(0));
Tree *tree = init_tree();
#define MAX_OP 10
for (int i = 0; i < MAX_OP; i++) {
int val = rand() % 100;
insert(tree, val);
printf("tree(%2d):", tree->length);
output_node(tree->root);
printf("\n");
}
printf("pre :");pre_order_node(tree->root); printf("\n");
printf("in :");in_order_node(tree->root); printf("\n");
printf("post:");post_order_node(tree->root);printf("\n");
#undef MAX_OP
clear_tree(tree);
return 0;
}
③广义表转二叉树(自建栈)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/***广义表 A (B (, D) , C(E,) ) 还原为二叉排序树
* 自建栈,自建树
*
*/
typedef struct Node {
//二叉树节点
char data;
struct Node *lchild, *rchild;
} Node;
typedef struct Tree {
Node *root;
int length;
} Tree;
typedef struct Stack {
Node **data;//data指针存“Node *”类型数据
int top, capacity;
} Stack;
Node *GetNewNode(char val) {
Node *p = (Node *)malloc(sizeof(Node));
p->data = val;
p->lchild = p->rchild = NULL;
return p;
}
void ClearNode(Node *root) {
if (root == NULL) return ;
ClearNode(root->lchild);
ClearNode(root->rchild);
free(root);
return ;
}
Tree *GetNewTree() {
Tree *tree = (Tree *)malloc(sizeof(Tree));
tree->root = NULL;
tree->length = 0;
return tree;
}
void ClearTree(Tree *tree) {
if (tree == NULL) return ;
ClearNode(tree->root);
free(tree);
return ;
}
Stack *GetNewStack(int n) {
Stack *stack = (Stack *)malloc(sizeof(Stack));
stack->data = (Node **)malloc(sizeof(Node *) * n);
stack->capacity = n;
stack->top = -1;
return stack;
}
void ClearStack(Stack *stack) {
if (stack == NULL) return ;
free(stack->data);
free(stack);
return ;
}
int empty(Stack *stack) {
return stack->top == -1;
}
Node *top(Stack *stack) {
return stack->data[stack->top];
}
int push(Stack *stack, Node *node) {
if (stack == NULL) return 0;
if (stack->top == stack->capacity - 1) return 0;
stack->data[++(stack->top)] = node;
return 1;
}
int pop(Stack *stack) {
if (stack == NULL) return 0;
if (empty(stack)) return 0;
stack->top -= 1;
return 1;
}
Node *build(const char *str, int *node_num){
//返回值为整个树的根节点
Stack *s = GetNewStack(strlen(str));//初始化栈的大小为strlen(str)
int flag = 0;//标记有没有逗号出现,标识该字母在逗号之前还是之后
Node *temp = NULL, *p = NULL;
while(str[0]){
switch (str[0]){
case '(': {
//遇到左括号入栈
push(s, temp);
flag = 0;
}break;
case ')': {
//遇到右括号出栈
p = top(s);//记录栈顶元素
pop(s);
}break;
case ',': flag = 1;break;//flag标记,为上一个节点的右孩子
case ' ': break;//遇到空格不进行操作
default: //遇字母,构建为树的节点
temp = GetNewNode(str[0]);
if(!empty(s) && flag == 0){
//栈顶不为空
top(s)->lchild = temp;//将所构建的节点设为栈顶元素的左孩子
}else if(!empty(s) && flag == 1){
top(s)->rchild = temp;
}
++(*node_num);//节点个数加一
break;
}
++str;//将字符串的地址+1
}
ClearStack(s);
if(temp && !p) p = temp;//特殊处理当树只有一个节点的情况,此时p为空
return p;//返回最后一次弹栈的元素即为根
}
void pre_order_node(Node *root) {
if (root == NULL) return;
printf("%c ", root->data);
pre_order_node(root->lchild);
pre_order_node(root->rchild);
return ;
}
void pre_order(Tree *tree) {
if (tree == NULL) return;
printf("pre_order(%d) : ", tree->length);
pre_order_node(tree->root);
printf("\n");
return ;
}
void in_order_node(Node *root) {
if (root == NULL) return;
in_order_node(root->lchild);
printf("%c ", root->data);
in_order_node(root->rchild);
return ;
}
void in_order(Tree *tree) {
if (tree == NULL) return;
printf("in_order(%d) : ", tree->length);
in_order_node(tree->root);
printf("\n");
return ;
}
void post_order_node(Node *root) {
if (root == NULL) return;
post_order_node(root->lchild);
post_order_node(root->rchild);
printf("%c ", root->data);
return ;
}
void post_order(Tree *tree) {
if (tree == NULL) return;
printf("post_order(%d) : ", tree->length);
post_order_node(tree->root);
printf("\n");
return ;
}
int main(){
char str[1000] = {
0};
int node_num = 0;
scanf("%[^\n]s",str);//输入带有空格的字符串 A (B (, D) , C(E) )
getchar();//吞掉上一个空格
Tree *tree = GetNewTree();
tree->root = build(str, &node_num);
tree->length = node_num;
pre_order(tree);
in_order(tree);
post_order(tree);
return 0;
}