学习数据结构的第七天

文章介绍了使用C语言实现树的两种存储结构(孩子表示法和孩子兄弟表示法),并将其应用到模拟栈的问题中,解决日志分析中的查询最大集装箱重量问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

树的存储结构的表示:

孩子表示法

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

#define MAX_CHILDREN 10 // 最多子节点数

// 树的节点结构体
typedef struct TreeNode {
    int value; // 节点存储的值
    struct TreeNode *child[MAX_CHILDREN]; // 子节点指针数组
} TreeNode;

// 创建一个新节点
TreeNode* create_node(int value) {
    TreeNode *node = (TreeNode*)malloc(sizeof(TreeNode));
    node->value = value;
    for(int i=0; i<MAX_CHILDREN; i++) {
        node->child[i] = NULL;
    }
    return node;
}

// 添加子节点
void add_child(TreeNode *parent, TreeNode *child) {
    for(int i=0; i<MAX_CHILDREN; i++) {
        if(parent->child[i] == NULL) {
            parent->child[i] = child;
            break;
        }
    }
}

// 遍历树
void traverse_tree(TreeNode *root) {
    if(root == NULL) {
        return;
    }
    printf("%d ", root->value);
    for(int i=0; i<MAX_CHILDREN; i++) {
        traverse_tree(root->child[i]);
    }
}

int main() {
    // 创建一棵树
    TreeNode *root = create_node(1);
    TreeNode *node2 = create_node(2);
    TreeNode *node3 = create_node(3);
    TreeNode *node4 = create_node(4);
    TreeNode *node5 = create_node(5);
    TreeNode *node6 = create_node(6);

    add_child(root, node2);
    add_child(root, node3);
    add_child(node2, node4);
    add_child(node2, node5);
    add_child(node3, node6);

    // 遍历树
    traverse_tree(root);

    return 0;
}

孩子兄弟表示法

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

// 树的节点结构体
typedef struct TreeNode {
    int value; // 节点存储的值
    struct TreeNode *firstChild; // 第一个孩子节点指针
    struct TreeNode *rightSibling; // 右兄弟节点指针
} TreeNode;

// 创建一个新节点
TreeNode* create_node(int value) {
    TreeNode *node = (TreeNode*)malloc(sizeof(TreeNode));
    node->value = value;
    node->firstChild = NULL;
    node->rightSibling = NULL;
    return node;
}

// 添加孩子节点
void add_child(TreeNode *parent, TreeNode *child) {
    if (parent->firstChild == NULL) {
        parent->firstChild = child;
    } else {
        TreeNode *sibling = parent->firstChild;
        while (sibling->rightSibling != NULL) {
            sibling = sibling->rightSibling;
        }
        sibling->rightSibling = child;
    }
}

// 遍历树
void traverse_tree(TreeNode *root) {
    if (root == NULL) {
        return;
    }
    printf("%d ", root->value);
    traverse_tree(root->firstChild);
    traverse_tree(root->rightSibling);
}

int main() {
    // 创建一棵树
    TreeNode *root = create_node(1);
    TreeNode *node2 = create_node(2);
    TreeNode *node3 = create_node(3);
    TreeNode *node4 = create_node(4);
    TreeNode *node5 = create_node(5);
    TreeNode *node6 = create_node(6);

    add_child(root, node2);
    add_child(root, node3);
    add_child(node2, node4);
    add_child(node2, node5);
    add_child(node3, node6);

    // 遍历树
    traverse_tree(root);

    return 0;
}

下面是分享一道模拟栈的一道题

https://www.luogu.com.cn/problem/P1165

P1165 日志分析

题目描述

M 海运公司最近要对旗下仓库的货物进出情况进行统计。目前他们所拥有的唯一记录就是一个记录集装箱进出情况的日志。该日志记录了两类操作:第一类操作为集装箱入库操作,以及该次入库的集装箱重量;第二类操作为集装箱的出库操作。这些记录都严格按时间顺序排列。集装箱入库和出库的规则为先进后出,即每次出库操作出库的集装箱为当前在仓库里所有集装箱中最晚入库的集装箱。

出于分析目的,分析人员在日志中随机插入了若干第三类操作――查询操作。分析日志时,每遇到一次查询操作,都要报告出当前仓库中最大集装箱的重量。

输入格式

包含 N 行:

第一行为一个正整数 N,对应于日志内所含操作的总数。

接下来的 N 行,分别属于以下三种格式之一:

  • 格式 1:0 X,表示一次集装箱入库操作,正整数 X 表示该次入库的集装箱的重量。
  • 格式 2:1,表示一次集装箱出库操作,(就当时而言)最后入库的集装箱出库。
  • 格式 3:2,表示一次查询操作,要求分析程序输出当前仓库内最大集装箱的重量。

当仓库为空时你应该忽略出库操作,当仓库为空查询时你应该输出 00。

分析

:这就是一个栈的模拟,操作1就是进栈 ,操作2是出栈 ,操作3 是查询  所以就只需要用一个数组当做栈,另一个数组来记录最大重量

#include <stdio.h>
#define MAX_SIZE 200001

int stack[MAX_SIZE]; // 栈
int f[MAX_SIZE]; // 记录当前栈的最大值
int t = 0; // 栈顶指针

int main() {
    int n, x, y;
    scanf("%d", &n);
    f[0] = 0;

    for (int i = 1; i <= n; i++) {
        scanf("%d", &x);

        if (x == 0) {
            scanf("%d", &y);
            t++;
            stack[t] = y;
            f[t] = (y > f[t - 1]) ? y : f[t - 1];
        }
        else if (x == 1) {
            if (t != 0)
                t--;
        }
        else if (x == 2) {
            printf("%d\n", f[t]);
        }
    }

    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值