本节课实验课总体安排:
1、讲完线索化二叉树
2、二叉树的遍历(先序、中序、后序)
3、统计二叉树结点总数
一、二叉树的遍历和结点数字统计
#include <stdio.h>
#include <stdlib.h>
#define MAX_SIZE 100
typedef char ElemType;
// 二叉树结点结构定义
typedef struct btnode {
ElemType data;
struct btnode *lchild;
struct btnode *rchild;
} BTNode, *BTree;
// 顺序栈结构体定义(备用,可扩展非递归遍历)
typedef struct sqstack {
BTree *top;
BTree *base;
int stack_size;
} SqStack;
// 栈初始化
int init_stack(SqStack *sq) {
sq->base = (BTree *)malloc(MAX_SIZE * sizeof(BTree));
if (!sq->base) {
printf("栈初始化失败!\n");
return 0;
}
sq->top = sq->base;
sq->stack_size = MAX_SIZE;
return 1;
}
// 入栈
int push(SqStack *sq, BTree b) {
if (sq->top - sq->base >= sq->stack_size)
return 0;
*(sq->top++) = b;
return 1;
}
// 出栈
int pop(SqStack *sq, BTree *b) {
if (sq->top == sq->base)
return 0;
*b = *(--sq->top);
return 1;
}
// 判空
int judge_empty(SqStack sq) {
return sq.top == sq.base;
}
//--------------------------------------------
// 1. 用字符串建立二叉树(先序输入,# 表示空结点)
//--------------------------------------------
void create_btree(BTree *bt, const char *str, int *index) {
char ch = str[*index];
(*index)++;
if (ch == '#' || ch == '\0') {
*bt = NULL;
} else {
*bt = (BTree)malloc(sizeof(BTNode));
(*bt)->data = ch;
create_btree(&((*bt)->lchild), str, index);
create_btree(&((*bt)->rchild), str, index);
}
}
//--------------------------------------------
// 2. 递归遍历二叉树
//--------------------------------------------
void preorder(BTree bt) { // 先序遍历
if (bt != NULL) {
printf("%c ", bt->data);
preorder(bt->lchild);
preorder(bt->rchild);
}
}
void inorder(BTree bt) { // 中序遍历
if (bt != NULL) {
inorder(bt->lchild);
printf("%c ", bt->data);
inorder(bt->rchild);
}
}
void postorder(BTree bt) { // 后序遍历
if (bt != NULL) {
postorder(bt->lchild);
postorder(bt->rchild);
printf("%c ", bt->data);
}
}
//--------------------------------------------
// 3. 统计二叉树结点总数
//--------------------------------------------
void count_nodes(BTree bt, int *count) {
if (bt == NULL)
return;
(*count)++;
count_nodes(bt->lchild, count);
count_nodes(bt->rchild, count);
}
//--------------------------------------------
// 主函数
//--------------------------------------------
int main() {
BTree bt = NULL;
char str[100];
int index = 0, count = 0;
scanf("%s", str);
create_btree(&bt, str, &index);
preorder(bt);
printf("\n");
inorder(bt);
printf("\n");
postorder(bt);
printf("\n");
count_nodes(bt, &count);
printf("%d\n", count);
return 0;
}
二、各部分代码详细讲解
1 头文件和宏定义
#include <stdio.h>
#include <stdlib.h>
#define MAX_SIZE 100
- #include <stdio.h>:提供输入输出函数,例如 printf()、scanf()。
- #include <stdlib.h>:提供动态内存管理函数,如 malloc()、free(),还可用 exit() 终止程序。
- #define MAX_SIZE 100:定义常量 MAX_SIZE,用于栈的容量。
2 数据结构定义
(1) 二叉树结点结构
typedef char ElemType;
- 定义二叉树结点的数据类型为 char。
typedef struct btnode {
ElemType data;
struct btnode *lchild;
struct btnode *rchild;
} BTNode, *BTree;
BTNode:二叉树结点结构体,包含:
- data:存储结点数据。
- lchild:指向左孩子。
- rchild:指向右孩子。
- BTree:定义为 BTNode*,方便声明二叉树指针。
(2) 顺序栈结构(备用,用于非递归遍历)
typedef struct sqstack {
BTree *top;
BTree *base;
int stack_size;
} SqStack;
- base:指向栈底。
- top:指向栈顶(下一个入栈位置)。
- stack_size:栈容量。
- 注意:这个栈在主程序中没用到,是备用的,可用于后续非递归遍历。
(3) 栈操作函数
int init_stack(SqStack *sq) {
sq->base = (BTree *)malloc(MAX_SIZE * sizeof(BTree));
if (!sq->base) {
printf("栈初始化失败!\n");
return 0;
}
sq->top = sq->base;
sq->stack_size = MAX_SIZE;
return 1;
}
- init_stack:初始化栈
- 为栈分配内存。
- 设置栈顶指针指向栈底。
- 栈容量设为 MAX_SIZE。
int push(SqStack *sq, BTree b) {
if (sq->top - sq->base >= sq->stack_size)
return 0;
*(sq->top++) = b;
return 1;
}
- push:将结点入栈。
- 判断栈是否已满。
- 将结点放入栈顶,并移动栈顶指针。
int pop(SqStack *sq, BTree *b) {
if (sq->top == sq->base)
return 0;
*b = *(--sq->top);
return 1;
}
pop:从栈顶取出结点。
- 判断栈是否为空。
-
取出栈顶元素,并修改栈顶指针。
-
int judge_empty(SqStack sq) { return sq.top == sq.base; }
- 判断栈是否为空,返回 1(空)或 0(非空)。
✅ 总结:栈是备用结构,用于非递归遍历,主程序未使用。
3 用字符串建立二叉树
void create_btree(BTree *bt, const char *str, int *index) {
char ch = str[*index]; // 取当前字符
(*index)++; // 下标 +1
if (ch == '#' || ch == '\0') {
*bt = NULL; // 空结点
} else {
*bt = (BTree)malloc(sizeof(BTNode)); // 分配结点
(*bt)->data = ch; // 保存数据
create_btree(&((*bt)->lchild), str, index); // 左子树
create_btree(&((*bt)->rchild), str, index); // 右子树
}
}
- 用递归按 先序顺序 创建二叉树:
- # 表示空结点。
- 动态分配结点,保存数据。
- 递归建立左、右子树。
4 递归遍历二叉树
(1) 先序遍历
void preorder(BTree bt) {
if (bt != NULL) {
printf("%c ", bt->data); // 根
preorder(bt->lchild); // 左
preorder(bt->rchild); // 右
}
}
- 根 → 左 → 右。
(2) 中序遍历
void inorder(BTree bt) {
if (bt != NULL) {
inorder(bt->lchild); // 左
printf("%c ", bt->data); // 根
inorder(bt->rchild); // 右
}
}
- 左 → 根 → 右。
(3) 后序遍历
void postorder(BTree bt) {
if (bt != NULL) {
postorder(bt->lchild); // 左
postorder(bt->rchild); // 右
printf("%c ", bt->data); // 根
}
}
- 左 → 右 → 根。
5 统计二叉树结点总数
void count_nodes(BTree bt, int *count) {
if (bt == NULL)
return; // 空结点直接返回
(*count)++; // 当前结点计数 +1
count_nodes(bt->lchild, count); // 左子树
count_nodes(bt->rchild, count); // 右子树
}
- 使用递归统计结点数:
- 空结点返回。
- 当前结点计数加 1。
- 左右子树递归累加。
6 主函数
int main() {
BTree bt = NULL; // 根结点初始化为空
char str[100]; // 输入字符串
int index = 0, count = 0;
准备二叉树指针、输入字符串、下标、计数。
scanf("%s", str); // 输入先序字符串
例如 "ABD##E##CF###"。
create_btree(&bt, str, &index); // 创建二叉树
preorder(bt); // 先序遍历
printf("\n");
inorder(bt); // 中序遍历
printf("\n");
postorder(bt); // 后序遍历
printf("\n");
输出三种遍历结果。
count_nodes(bt, &count); // 统计结点总数
printf("%d\n", count); // 输出结点数
return 0;
}

被折叠的 条评论
为什么被折叠?



