【发布时间】:2009-10-23 23:14:21
【问题描述】:
我正在尝试自学数据结构和算法。我用 C 编写了自己的双链表,现在我想编写一些算法来在列表上执行。交换列表项的首选方式是什么?交换内容还是重新排列指向下一个和上一个列表项的指针更好?
【问题讨论】:
标签: c algorithm data-structures
我正在尝试自学数据结构和算法。我用 C 编写了自己的双链表,现在我想编写一些算法来在列表上执行。交换列表项的首选方式是什么?交换内容还是重新排列指向下一个和上一个列表项的指针更好?
【问题讨论】:
标签: c algorithm data-structures
重新排列指针。交换数据项可能会产生副作用。特别是,您可能在函数之外的某处存储了对节点的引用,通常当您重新排列列表中节点的顺序时,您不希望人们持有对节点的引用突然发现节点指向新数据。这是因为节点的重要识别特征通常是它指向的数据而不是它在列表中的位置。
【讨论】:
规范交换是通过指针重新排列完成的,没有副作用,当然更快:
void swap (node *a, node *b) {
node *tmp;
tmp = a;
a = b;
b = tmp;
}
【讨论】:
根据存储在链表元素中的内容类型,交换元素的实际内容会很棘手(例如考虑不同长度字符串的链表),因此交换指针更容易指向下一个和上一个列表项。
【讨论】:
取决于您如何分配内容。
如果您要存储指向内容的指针,那么切换内容并不是什么大问题。如果您的节点中有一个大结构,那么切换指针可能比复制整个内容更有效。
【讨论】:
我倾向于支持大多数人已经说过的话。一些背景知识可能会有所帮助:交换指针可以保证工作,而交换对象可能并不总是像看起来那么简单。想想可能/将要创建的临时对象和异常(我的意思是一般而不是 C++ 语言功能方式)可能会发生并实际上使您的容器(列表)处于不良状态。在你的容器中寻找不变量——即交换应该保持列表大小不变,元素保持不变并在其上进行设计。
【讨论】:
是交换内容还是重新排列指向下一个和上一个列表项的指针更好?
重新排列指针,因为交换节点的所有元素可能会更加昂贵。
就时间复杂度而言,交换两个指针是恒定的操作。
但是,如果你想在两个节点之间交换所有元素,那么你需要访问它们,并与它们的对应部分交换它们,即 O(f),其中 f 是结构体的字段数表示节点拥有的数据(即节点拥有的数据数量)。
换句话说,交换节点数据是线性操作,而交换两个指针是常数。
交换数据可能会产生副作用,尤其是当您可能在函数之外的某个地方存储了对节点的引用时,这已经在接受的answer 中涵盖,但我也想指出这一事实。
【讨论】: