我目前正在研究面试准备的链接列表,如果有人能够对此有所了解,我将不胜感激。假设C中的以下函数在某个元素elem(作为函数的参数传递)之后将新元素插入到列表中:
bool insertAfter(Element * elem, int data){
Element * newElem, * curPos = head;
newElem->data = data;
while(curPos){
if(curPos == elem){
newElem->next = curPos->next;
curPos->next = newElem;
return true;
}
curPos = curPos->Next;
}
return false;
}
虽然我正在研究的教科书中指出了上述内容,但我尝试提出一种不使用任何迭代的解决方案:
bool insertAfter(Element * elem, int data){
Element * newElem;
newElem->next = elem->next
newElem->data = data
elem->next = newElem;
return true;
}
然而,由于它看起来过于简单化,我觉得它可能不起作用,但我不确定为什么。我需要一些关于为什么这可能有效或无效的技术细节的见解,谢谢。
答案 0 :(得分:2)
两个版本都遇到使用newElem
的错误,就像它是一个有效的指针一样。它不是。它未初始化为指向有效对象。
您可以在使用之前为对象分配内存来纠正错误:
Element * newElem = malloc(sizeof(*newElem));
两个版本之间的区别在于,如果elem
由于某种原因无法访问head
或NULL
,则第一个版本对现有列表无效。第二个版本不处理这两种情况。它假定elem
在列表中并且它不是NULL。
答案 1 :(得分:1)
这不起作用,因为你不知道你的newElem
。在链表中,您可以了解有关头部的信息,每个元素都可以为您提供查找下一个元素的信息:
head -> e1 -> e2 -> ...
所以你需要迭代,直到找到你关心的元素。但您也可以使用递归进行迭代。
答案 2 :(得分:1)
您的逻辑将起作用,因为您只需要指向要插入节点的节点的指针。如果您已经有这样的指针,则无需迭代并搜索节点。
但是,如果没有要插入新节点的节点指针,则搜索(迭代)将是相关的。示例:假设节点具有唯一键,并且您没有存在键的节点指针,并且在找到包含特定键的节点后要插入,则需要找到正确的节点指针并进行插入(函数应该接受key作为参数)。
但是在您的代码中(两种情况),您还没有为新节点分配内存。您需要为新节点执行malloc
,然后继续插入。
答案 3 :(得分:1)
您的解决方案非常正确。示例中的迭代几乎完全没用。
示例函数正在做的是:给定一个元素以插入新数据之后,它会查看以head
开头的列表来查找相同的元素,然后插入数据 - 找到head
或elem
后无效。因为所有循环都是"找到"
唯一可能的用途是将插入功能限制为仅在整个程序中以全局head
开头的一个列表上工作。这是一个奇怪的设计决策,人们可能会认为这是一个错误,除非有理由相信(动态数据结构受限于单个实例是一个不寻常的模式;更重要的是,整点链接列表的em>是O(1)插入,其中示例函数通过添加此无用循环而中断)。除了强制执行此约束之外,其他任何原因都不需要head
,如果 ,那么将它作为参数传递更有意义,以便函数是能够在每个程序的多个列表中使用。 (或者,根本不执行检查:链接列表的另一个用途是你可以传递并插入节点之后不用担心head元素。)
正如其他人所指出的那样,你实际上没有分配newElem
,但教科书也是如此。总的来说,这是一个垃圾的例子;作者不仅在分配时犯了错误,而且他们似乎也不了解使用链接列表的基本优势。你一定要怀疑地对待这本教科书。