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

文章描述了一个使用C语言编写的程序,该程序创建了一个基于链式存储的树形结构,其中节点包含数据、父节点、子节点和兄弟节点指针。程序通过读取输入数据构建树,并使用递归方法在树中查找特定节点,找到则输出yes,否则输出no。在main函数中,程序读取节点信息,创建节点并构建树的结构,最后释放所有节点的内存。

要求功能

读入相应数据以链式存储方式创建树形结构(即表头结点表+边表的邻接表形式),输入待查找的结点名称,判断该结点是否在树中,是则打印"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;
}
<think>我们正在解决运行roLabelImg.py时出现的两个问题:1.TypeError:'NoneType'object isnot iterable2. libpng warning: iCCP: knownincorrect sRGB profile首先,我们需要分析错误原因。第一个错误:TypeError: 'NoneType' objectis notiterable这通常发生在试图迭代一个值为None的对象时。在roLabelImg.py中,可能是在某个函数返回了None,而代码试图将其作为可迭代对象(如列表、元组)处理。第二个错误:libpng warning: iCCP: knownincorrect sRGB profile这是一个关于PNG图像文件的警告,表明图像中的iCCP块包含的sRGB配置文件可能不正确。这通常不会导致程序崩溃,但可能会影响图像显示。不过,有时这个警告可能会被错误地处理,导致后续问题。由于我们无法直接看到roLabelImg.py的源代码,但根据常见的roLabelImg实现(用于旋转目标标注),我们可以推测可能的原因。常见原因及解决方案:对于TypeError:'NoneType'object isnot iterable:1.图像路径问题:程序可能没有正确读取到图像,导致返回None。检查图像路径是否正确,图像文件是否存在。2.图像解码问题:由于libpng警告,可能在某些图像读取时出现问题,导致返回None。虽然警告通常不会导致读取失败,但某些库的处理可能不同。对于libpng警告:1.这个警告通常可以忽略,但如果你想消除它,可以重新保存图像文件,去掉有问题的iCCP块。可以使用图像处理工具(如Photoshop、GIMP)或命令行工具(如ImageMagick)重新保存PNG文件。具体步骤:步骤1:检查图像路径和文件确保你正在标注的图像文件路径正确,并且文件没有损坏。可以尝试用其他图像查看器打开这些图像。步骤2:调试代码找到引发TypeError的位置在roLabelImg.py中,找到引发错误的具体行。你可以在运行脚本时查看错误堆栈,或者添加打印语句来调试。例如,错误可能是这样的:File "roLabelImg.py", lineX, infunction Yfor itemin some_variable:TypeError: 'NoneType' objectis notiterable找到该行后,检查为什么some_variable是None。可能是之前的某个函数调用返回了None。步骤3:处理图像读取问题在roLabelImg中,通常使用OpenCV或PIL读取图像。检查读取图像的代码部分,确保读取成功。例如,使用OpenCV:image =cv2.imread(image_path)if imageis None:print(f"Failedto readimage:{image_path}")如果读取失败,则跳过该图像或处理错误。步骤4:处理libpng警告虽然警告本身可能不是导致TypeError的原因,但为了消除警告,可以尝试以下方法:方法一:使用工具批量修复PNG文件使用ImageMagick的mogrify命令:mogrify-strip*.png这会移除PNG文件中的元数据,包括有问题的iCCP块。方法二:在代码中忽略警告(不推荐,但可以临时解决)在Python中,可以通过设置环境变量或使用OpenCV的忽略警告功能。但OpenCV本身不提供忽略特定警告的方法,所以更好的方法是修复图像文件。方法三:在读取图像前设置环境变量(针对libpng)import osos.environ['OPENCV_IO_ENABLE_JASPER'] ='0'os.environ['OPENCV_IO_ENABLE_JASPER_DEBUG']= '1'但这些变量可能不适用于此警告。另一种方法是使用PIL读取图像,因为PIL可能对警告的处理更宽容。如果roLabelImg使用的是OpenCV,可以尝试改用PIL读取,然后转换为OpenCV格式(BGR)。例如:from PILimport Imageimport numpyas npimage= Image.open(image_path)image= np.array(image)#如果使用OpenCV,可能需要转换颜色空间#image =image[:, :, ::-1].copy()# RGBto BGR但是,修改roLabelImg的读取方式可能需要改动代码。步骤5:修复roLabelImg.py代码假设在调试中我们发现错误发生在以下代码段:shapes= self.canvas.coords#假设这里返回None那么我们需要确保self.canvas.coords不会返回None。或者,在另一个常见场景:在加载图像时,如果图像读取失败,后续处理就会出错。因此,在读取图像后应检查图像是否为空。例如,在roLabelImg.py中找到加载图像的函数(可能是loadImage函数),添加检查:ifself.image isNone:#显示错误信息return具体代码位置需要根据实际错误堆栈来确定。由于没有具体的代码,我们只能提供一般性建议。考虑到用户可能无法修改所有图像文件,我们可以在代码中捕获警告并忽略,同时确保图像读取正常。以下是一个在代码中忽略libpng警告的示例(使用warnings模块):importwarningswarnings.filterwarnings("ignore",message="iCCP: knownincorrect sRGB profile")但请注意,这可能会隐藏其他警告。另一种方法是使用日志过滤器,但同样,这只能隐藏警告,不能解决图像读取失败的问题。综合以上,我们建议:1.首先修复TypeError,因为它是错误,会中断程序。通过调试找到返回None的位置,然后检查为什么返回None(可能是图像读取失败,路径错误等)。2.然后处理libpng警告,通过修复图像文件或忽略警告。如果问题仍然存在,请提供具体的错误堆栈信息,以便更精确地定位问题。由于问题描述中提到了两个错误,我们假设TypeError可能是由图像读取失败(返回None)引起的,而图像读取失败又可能与libpng警告有关(尽管通常不会)。因此,先修复图像文件可能是根本解决之道。推荐操作顺序:1.使用mogrify修复所有PNG图像。2.确保roLabelImg.py能够正确读取图像(在代码中添加图像读取检查)。3.如果问题仍然存在,再调试TypeError的具体位置。如果用户没有ImageMagick,可以安装它(在Ubuntu上:sudo aptinstall imagemagick;在Windows上,可以从官网下载安装)。如果用户有很多图像,可以批量修复。如果用户不想修复图像,可以尝试在代码中忽略警告,并确保即使有警告图像也能正常读取(但根据错误,TypeError可能是由于图像读取为None引起的,所以必须确保图像读取不为None)。因此,重点在于确保图像被正确读取。下面我们给出一个在roLabelImg.py中可能添加的代码修改示例:在加载图像的函数中(可能是loadImage或类似函数),使用OpenCV读取图像,并检查是否读取成功:self.image =cv2.imread(str(filePath),cv2.IMREAD_COLOR)ifself.imageis None:#尝试用PIL读取try:from PILimport Imageimport numpyas nppil_image= Image.open(str(filePath))self.image= np.array(pil_image)#转换颜色空间,因为OpenCV使用BGR,而PIL是RGBself.image =cv2.cvtColor(self.image,cv2.COLOR_RGB2BGR)except Exceptionas e:print(f"Failedto readimage withbothOpenCV andPIL:{str(filePath)}")print(e)#处理错误,例如返回或跳过returnFalse#然后继续后续处理但是,请注意,原roLabelImg.py可能已经使用了PIL,或者使用了其他方式。因此,需要根据实际情况调整。由于没有具体代码,以上只是通用建议。最后,如果用户提供了具体的错误堆栈,我们可以给出更具体的代码修改位置。相关问题:1.如何安装ImageMagick来修复PNG文件?2.在Python中如何忽略特定警告?3.如何修改roLabelImg.py的代码以检查图像读取失败?4.使用OpenCV和PIL读取图像有什么区别?5.除了iCCP警告,还有哪些常见的图像读取问题?</think>### 解决 roLabelImg.py 的 TypeError 和 libpng 警告问题 #### 问题分析 1. **TypeError: 'NoneType' object is not iterable** 通常发生在代码试图迭代一个值为 `None` 的对象时,常见原因包括: - 图像文件路径错误或文件损坏 - OpenCV/PIL 读取图像失败(返回 `None`) - 标注文件解析失败(如 XML/JSON 文件格式错误) 2. **libpng warning: iCCP: known incorrect sRGB profile** 这是 PNG 图像的元数据问题,不影响图像显示但可能干扰程序: - 图像编辑软件(如 Photoshop)保存时添加了非标准色彩配置 - OpenCV/PyQt 的 PNG 解码器对此敏感 --- #### 解决方案 ##### 步骤 1:修复 TypeError **方法 1:检查图像路径和文件** ```python # 在 roLabelImg.py 中找到图像加载代码(通常为 loadImage() 函数) # 添加文件存在性检查 import os def loadImage(self, imagePath): if not os.path.exists(imagePath): print(f"错误:文件不存在 {imagePath}") return False # 原始图像加载代码... ``` **方法 2:捕获图像读取异常** ```python # 在图像加载代码中(如使用 OpenCV) import cv2 def loadImage(self, imagePath): try: image = cv2.imread(imagePath) if image is None: # 检查是否读取失败 raise ValueError("OpenCV 读取失败") except Exception as e: print(f"图像读取错误: {e}") # 尝试用 PIL 回退读取 from PIL import Image try: image = Image.open(imagePath) # 改用 PIL 读取 image = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR) except: print("PIL 读取也失败,请检查文件格式") return False ``` **方法 3:检查标注文件解析** ```python # 在解析标注文件的函数中(如 parseXML()) def parseXML(xml_path): try: tree = ET.parse(xml_path) root = tree.getroot() # 确保对象列表存在 objects = root.findall('object') if objects is None: # 防止空对象 return [] except ET.ParseError: print("XML 解析错误,文件可能损坏") return [] # 返回空列表避免 None ``` ##### 步骤 2:修复 libpng 警告 **方法 1:批量修复 PNG 文件(推荐)** ```bash # 安装 ImageMagick sudo apt-get install imagemagick # Linux brew install imagemagick # macOS # 递归修复当前目录下所有 PNG find . -name "*.png" -exec mogrify -strip {} \; ``` **方法 2:在代码中忽略警告** ```python # 在 roLabelImg.py 开头添加 import os os.environ["OPENCV_IO_IGNORE_WARNINGS"] = "1" # 忽略 OpenCV 警告 import cv2 # 或过滤 libpng 警告 import warnings warnings.filterwarnings("ignore", message="iCCP") ``` **方法 3:转换图像格式** ```python # 在图像加载前转换格式 from PIL import Image def convert_image(src_path, dst_path): img = Image.open(src_path) img.save(dst_path, format="PNG", optimize=True) # 重新保存可修复元数据 ``` --- #### 验证步骤 1. 运行修复脚本后重启 roLabelImg 2. 测试不同图像文件(JPEG/PNG) 3. 检查标注文件格式是否合规(参考 Pascal VOC/COCO) > **注意**:如果使用 Docker 环境,需确保挂载的镜像文件已修复: > ```bash > docker run -v $(pwd)/fixed_images:/data ... > ``` --- ### 相关问题 1. 如何批量修复包含损坏元数据的 PNG 文件? 2. OpenCV 读取图像返回 `None` 的其他常见原因有哪些? 3. 旋转目标标注工具(roLabelImg)的工作原理是什么? 4. 如何为 roLabelImg 添加自定义图像预处理钩子? 5. Docker 环境中如何处理图像文件的读写权限问题? [^1]: 关于 OpenCV 图像读取问题的官方文档 [^2]: PNG 元数据修复的 ImageMagick 最佳实践 [^3]: roLabelImg 常见错误解决方案的 GitHub Issue 追踪
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值