在C语言中,可以通过**先序遍历的方式输入数据**来创建一个二叉链表表示的二叉树

在C语言中,可以通过先序遍历的方式输入数据来创建一个二叉链表表示的二叉树。通常约定以某个特殊值(如 -1)表示空结点,用于标识子树的结束。

🌲 创建思路(递归方式)

根据先序遍历的顺序:根 → 左 → 右,我们依次读入数据:

  • 若输入为 -1,表示该子树为空,返回 NULL
  • 否则,为当前节点分配内存,赋值,并递归创建左子树和右子树。

✅ C语言实现代码

#include <stdio.h>
#include <stdlib.h>

// 二叉树结点定义
typedef struct BiTNode {
    int data;
    struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;

// 按先序输入数据创建二叉树(-1 表示空结点)
void CreateBiTree(BiTree *root) {
    int val;
    scanf("%d", &val);

    if (val == -1) {
        *root = NULL;  // 空结点
    } else {
        *root = (BiTNode*)malloc(sizeof(BiTNode));
        if (!*root) {
            printf("内存分配失败!\n");
            exit(1);
        }
        (*root)->data = val;           // 设置根节点数据
        CreateBiTree(&(*root)->lchild); // 递归创建左子树
        CreateBiTree(&(*root)->rchild); // 递归创建右子树
    }
}

// 示例:先序遍历输出验证
void PreOrder(BiTree root) {
    if (root != NULL) {
        printf("%d ", root->data);
        PreOrder(root->lchild);
        PreOrder(root->rchild);
    }
}

// 主函数测试
int main() {
    BiTree T;
    printf("请输入先序序列构建二叉树(-1 表示空结点):\n");
    CreateBiTree(&T);

    printf("先序遍历结果为:");
    PreOrder(T);
    printf("\n");

    return 0;
}

🧪 输入示例

假设我们要构建如下二叉树:

        1
       / \
      2   3
     / \
    4   5

对应的先序输入序列为(补全空指针用 -1):

1 2 4 -1 -1 5 -1 -1 3 -1 -1

每个 -1 对应一个空左右孩子,完整反映树结构。


🔍 注意事项

  • 必须严格按照先序结构输入,包括所有叶子结点的左右空指针。
  • 使用指针的地址(BiTree *root)是为了修改实参指针本身。
  • 动态内存分配需检查是否成功,避免野指针或崩溃。

// 一、二叉链表的结点类型定义
typedef struct BiTNode {
    int data;
    struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;

// 二、二叉树的遍历方式

// 先序遍历:根 → 左 → 右
void PreOrder(BiTree root) {
    if (root != NULL) {
        printf("%d ", root->data);      // 访问根节点
        PreOrder(root->lchild);         // 遍历左子树
        PreOrder(root->rchild);         // 遍历右子树
    }
}

// 中序遍历:左 → 根 → 右
void InOrder(BiTree root) {
    if (root != NULL) {
        InOrder(root->lchild);          // 遍历左子树
        printf("%d ", root->data);      // 访问根节点
        InOrder(root->rchild);          // 遍历右子树
    }
}

// 后序遍历:左 → 右 → 根
void PostOrder(BiTree root) {
    if (root != NULL) {
        PostOrder(root->lchild);        // 遍历左子树
        PostOrder(root->rchild);        // 遍历右子树
        printf("%d ", root->data);      // 访问根节点
    }
}

通过先序遍历中序遍历序列可以唯一重建一棵二叉树(前提是不含重复值)。

🔍 重建原理

  • 先序遍历:顺序为 根 → 左子树 → 右子树,所以第一个元素就是当前子树的根节点
  • 中序遍历:顺序为 左子树 → 根 → 右子树,因此可以在中序序列中找到根的位置,从而划分出左右子树的范围。

利用这两个特性,可以递归构造二叉树


✅ 算法步骤

  1. 从先序序列中取出当前根节点(初始为第一个元素)。
  2. 在中序序列中查找该根的位置,将其分为:
    • 左半部分:左子树的中序序列
    • 右半部分:右子树的中序序列
  3. 根据左子树结点数量,确定先序序列中对应的部分。
  4. 递归构建左子树和右子树。

✅ C语言实现代码

#include <stdio.h>
#include <stdlib.h>

// 二叉树结点定义
typedef struct BiTNode {
    int data;
    struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;

// 查找元素在数组中的位置
int search(int arr[], int start, int end, int value) {
    for (int i = start; i <= end; i++) {
        if (arr[i] == value)
            return i;
    }
    return -1;
}

// 使用先序和中序序列重建二叉树
BiTree buildTree(int preorder[], int inorder[], int preStart, int inStart, int inEnd) {
    if (inStart > inEnd)
        return NULL;

    // 创建根节点(当前先序起点)
    BiTree root = (BiTNode*)malloc(sizeof(BiTNode));
    if (!root) {
        printf("内存分配失败!\n");
        exit(1);
    }
    root->data = preorder[preStart];
    root->lchild = root->rchild = NULL;

    // 如果没有子树(叶子),直接返回
    if (inStart == inEnd)
        return root;

    // 在中序中找根的位置,划分左右子树
    int inRootIndex = search(inorder, inStart, inEnd, root->data);

    // 计算左子树结点数
    int leftSubtreeSize = inRootIndex - inStart;

    // 递归构建左子树和右子树
    root->lchild = buildTree(preorder, inorder, preStart + 1, inStart, inRootIndex - 1);
    root->rchild = buildTree(preorder, inorder, preStart + leftSubtreeSize + 1, inRootIndex + 1, inEnd);

    return root;
}

// 中序遍历验证结果
void InOrder(BiTree root) {
    if (root != NULL) {
        InOrder(root->lchild);
        printf("%d ", root->data);
        InOrder(root->rchild);
    }
}

// 先序遍历验证结果
void PreOrder(BiTree root) {
    if (root != NULL) {
        printf("%d ", root->data);
        PreOrder(root->lchild);
        PreOrder(root->rchild);
    }
}

// 主函数测试
int main() {
    int n;
    printf("请输入节点个数:");
    scanf("%d", &n);

    int preorder[n], inorder[n];

    printf("请输入先序遍历序列:");
    for (int i = 0; i < n; i++)
        scanf("%d", &preorder[i]);

    printf("请输入中序遍历序列:");
    for (int i = 0; i < n; i++)
        scanf("%d", &inorder[i]);

    BiTree T = buildTree(preorder, inorder, 0, 0, n - 1);

    printf("重建完成!\n");
    printf("先序遍历验证:");
    PreOrder(T);
    printf("\n");
    printf("中序遍历验证:");
    InOrder(T);
    printf("\n");

    return 0;
}

🧪 示例输入输出

假设:

  • 先序:[1, 2, 4, 5, 3]
  • 中序:[4, 2, 5, 1, 3]

程序将重建如下二叉树:

        1
       / \
      2   3
     / \
    4   5

输出验证:

  • 先序:1 2 4 5 3
  • 中序:4 2 5 1 3

⚠️ 注意事项

  • 所有节点值应不重复,否则 search 函数可能定位错误。
  • 数组长度需一致,且输入合法。
  • 可优化使用哈希表(如静态映射数组)加速查找(适用于数据范围小的情况)。

在这里插入图片描述

下载方式:https://pan.quark.cn/s/a4b39357ea24 布线问题(分支限界算法)是计算机科学和电子工程领域中一个广为人知的议题,它主要探讨如何在印刷电路板上定位两个节点间最短的连接路径。 在这一议题中,电路板被构建为一个包含 n×m 个方格的矩阵,每个方格能够被界定为可通行或不可通行,其核心任务是定位从初始点到最终点的最短路径。 分支限界算法是处理布线问题的一种常用策略。 该算法与回溯法有相似之处,但存在差异,分支限界法仅需获取满足约束条件的一个最优路径,并按照广度优或最小成本优的原则来探索解空间树。 树 T 被构建为子集树或排列树,在探索过程中,每个节点仅被赋予一次成为扩展节点的机会,且会一次性生成其全部子节点。 针对布线问题的解决,队列式分支限界法可以被采用。 从起始位置 a 出发,将其设定为首个扩展节点,并将与该扩展节点相邻且可通行的方格加入至活跃节点队列中,将这些方格标记为 1,即从起始方格 a 到这些方格的距离为 1。 随后,从活跃节点队列中提取队首节点作为下一个扩展节点,并将与当前扩展节点相邻且未标记的方格标记为 2,随后将这些方格存入活跃节点队列。 这一过程将持续进行,直至算法探测到目标方格 b 或活跃节点队列为空。 在实现上述算法时,必须定义一个类 Position 来表征电路板上方格的位置,其成员 row 和 col 分别指示方格所在的行和列。 在方格位置上,布线能够沿右、下、左、上四个方向展开。 这四个方向的移动分别被记为 0、1、2、3。 下述表格中,offset[i].row 和 offset[i].col(i=0,1,2,3)分别提供了沿这四个方向前进 1 步相对于当前方格的相对位移。 在 Java 编程语言中,可以使用二维数组...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Bol5261

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值