为何我的链表搜索for循环在if条件不满足后无法匹配后续节点?
链表搜索方法的匹配问题
我实现的链表类search方法存在逻辑错误:名为“Find Nodes With Kind”的for循环,在if语句首次判断不匹配后,无法再匹配后续同类型的节点。我尝试过添加大括号、改用while循环,结果完全一致,且已在CLion和OnlineGDB.com中测试过。
程序无编译或运行报错,但行为不符合预期:
- 当目标类型KIND与第0个节点的Bead类型(例如copper)相同时,返回的指针仅包含第0个节点及后续连续相同类型的所有位置,第一个不匹配节点之后的同类型节点不会被纳入结果;
- 当搜索类型与第0个节点不同(例如第0个是silver,搜索copper),方法直接返回
nullptr。
相关代码
list.h
/* list.h */ /* ...blah, blah, blah... */ // 枚举数据类型 // 珠子类型 enum Bead: unsigned char{copper, silver, gold}; // 全局常量 const unsigned char X0 = 0, X1 = 1; /* ...其他内容... */ class List { /* ...无关内容...*/ // 结构体/类 struct Node // 链表的节点结构 { // 成员变量 Bead kind; // 存储珠子类型 Node * next; // 指向下一个节点的指针 /* ...其他内容... */ }; // 成员变量 Node * head; /* ...其他内容... */ public: /* ...其他内容... */ // 成员方法 size_t length() const; // 获取链表长度 /* ...其他内容... */ }; /* ...其他内容... */
list.cpp
/* list.cpp */ /* ...blah, blah, blah... */ // 搜索方法 size_t * List::search(const Bead & KIND) { // 方法变量/常量 List::Node * node = head; // 遍历链表的指针 const size_t L {length()}, // 链表长度 LP1 {L + X1}; // 链表长度+1,用于存储结果的数组大小 size_t position[LP1], // 存储找到的位置 newSize = X1, // 返回数组的大小 * returned; // 要返回的数组指针 // 空链表检查 if(!head) return nullptr; // 空链表直接返回nullptr // 查找匹配类型的节点 for(size_t i = X0; i < L; ++i) // 遍历到链表末尾: if(node->kind == KIND) // 如果找到匹配类型: { // 将位置存入position数组 position[newSize++] = i; // 更新返回数组的大小 node = node->next; // 移动到下一个节点 } // 遍历结束后,将position[0]设为返回数组的大小 position[X0] = newSize; // 如果找到匹配项,返回结果数组 if(newSize > X1) { returned = new size_t[newSize]; // 创建对应大小的数组 for(size_t i = X0; i < newSize; ++i) // 复制数据 *(returned + i) = position[i]; return returned; // 返回数组指针 } // 未找到匹配项,返回nullptr return nullptr; } /* ...其他内容... */
问题原因
核心错误在于:只有当节点类型匹配时,才会执行node = node->next;移动指针。
- 当遇到第一个不匹配的节点时,循环变量
i继续递增,但node始终停留在这个不匹配的节点上,后续循环一直判断同一个节点,自然无法找到后面的匹配项; - 如果第一个节点就不匹配,
node完全不会移动,整个循环结束后没有任何匹配记录,直接返回nullptr。
修复方案
把node = node->next;移到if语句外部,确保无论当前节点是否匹配,每次循环都移动指针遍历下一个节点:
// 查找匹配类型的节点 for(size_t i = X0; i < L; ++i) // 遍历到链表末尾: { if(node->kind == KIND) // 如果找到匹配类型: { // 将位置存入position数组 position[newSize++] = i; // 更新返回数组的大小 } node = node->next; // 无论匹配与否,都移动到下一个节点 }
修复后,方法会遍历链表的所有节点,收集所有匹配目标类型的位置,无论这些节点是否连续,也不管第一个节点是否匹配。
内容的提问来源于stack exchange,提问作者Pål Hart
相关产品推荐
相关产品推荐

