数据结构实验六:树和二叉树

本节课实验课总体安排:

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;

}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值