【CUPK小学期】笔记2:树路径求解

要求功能

读入相应数据以链式存储方式创建树形结构(即表头结点表+边表的邻接表形式),输入待查找的结点名称,判断该结点是否在树中,是则打印"yes",否则打印"no"


程序演示 

样例输入+输出(no)


代码思路 

首先,定义一个树的节点结构,包含了节点的数据、父节点指针、子节点指针和兄弟节点指针。

然后,我们实现了创建节点的函数createNode,用于创建一个新的节点,并将节点的数据和指针初始化为空。

接下来,我们实现findNode函数,用于在树中查找是否存在某个节点。该函数采用递归的方式,在树的子节点和兄弟节点中查找目标节点。

然后,我们实现addChild函数,用于向树中添加子节点。该函数首先将子节点的父节点指针指向目标节点,然后根据目标节点的子节点是否为空来将子节点添加到目标节点的子节点链表中。

在main函数中,我们首先读取输入的节点数量n,并创建一个指针数组nodes来存储所有的节点指针。

然后,我们使用一个循环来读取每个节点的信息,并根据节点的父节点和子节点创建树的结构。在创建父节点时,我们先在已有的节点指针数组中查找是否已经存在该节点,如果存在则直接使用已有的节点指针,如果不存在则创建一个新的节点并将其加入节点指针数组中。

在创建子节点时,我们使用strtok函数将输入的子节点字符串按照'/'进行分割,并依次创建子节点并将其添加到父节点的子节点链表中。

最后,我们读取目标节点的数据,并调用findNode函数在树中查找目标节点。如果找到目标节点,则输出"yes",否则输出"no"。

最后,我们使用一个循环来释放所有的节点内存。


完整代码 

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

#define MAX_SIZE 100

// 树的结点定义
typedef struct Node {
    char data[MAX_SIZE];
    struct Node* parent;
    struct Node* child;
    struct Node* sibling;
} Node;

// 创建树的结点
Node* createNode(char* data) {
    Node* newNode = (Node*)malloc(sizeof(Node));
    strcpy(newNode->data, data);
    newNode->parent = NULL;
    newNode->child = NULL;
    newNode->sibling = NULL;
    return newNode;
}

// 在树中查找结点
int findNode(Node* root, char* target) {
    if (root == NULL) {
        return 0; // 树为空,返回0
    }
    if (strcmp(root->data, target) == 0) {
        return 1; // 找到目标结点,返回1
    }
    // 递归在子结点和兄弟结点中查找目标结点
    return findNode(root->child, target) || findNode(root->sibling, target);
}

// 添加孩子结点
void addChild(Node* parent, Node* child) {
    child->parent = parent;
    if (parent->child == NULL) {
        parent->child = child;
    } else {
        Node* sibling = parent->child;
        while (sibling->sibling != NULL) {
            sibling = sibling->sibling;
        }
        sibling->sibling = child;
    }
}

int main() {
    int n;
    scanf("%d", &n);
    getchar(); // 读取换行符

    Node* root = NULL; // 树的根结点
    Node* nodes[MAX_SIZE]; // 用于存储所有结点的指针

    // 读取结点信息并创建树结构
    for (int i = 0; i < n; i++) {
        char parent[MAX_SIZE];
        char children[MAX_SIZE];
        scanf("%s", parent);
        getchar(); // 读取换行符
        scanf("%[^\n]", children);
        getchar(); // 读取换行符

        Node* parentNode = NULL;
        Node* childNode = NULL;

        // 查找或创建父结点
        for (int j = 0; j < i; j++) {
            if (strcmp(nodes[j]->data, parent) == 0) {
                parentNode = nodes[j];
                break;
            }
        }
        if (parentNode == NULL) {
            parentNode = createNode(parent);
            nodes[i] = parentNode;
        }

        // 创建并添加子结点
        char* child = strtok(children, "/");
        while (child != NULL) {
            childNode = createNode(child);
            addChild(parentNode, childNode);
            nodes[i + 1] = childNode;
            i++;
            child = strtok(NULL, "/");
        }
    }

    char target[MAX_SIZE];
    scanf("%s", target);

    // 在树中查找目标结点
    if (findNode(root, target)) {
        printf("yes\n");
    } else {
        printf("no\n");
    }

    // 释放内存
    for (int i = 0; i < n; i++) {
        free(nodes[i]);
    }

    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值