拆分链表有两部分

时间:2013-07-22 07:40:52

标签: c algorithm linked-list

给定一个列表,将其拆分为两个子列表 - 一个用于前半部分,一个用于后半部分。如果元素的数量是奇数,则额外元素应该放在前面的列表中。因此,列表FrontBackSplit()上的{2, 3, 5, 7, 11}应该会产生两个列表{2, 3, 5}{7, 11}

代码就是这个。

void FrontBackSplit(Node *head, Node **front, Node **back) {
  if (!head) return;  // Handle empty list
  Node *front_last_node;
  Node *slow = head;
  Node *fast = head;
  while (fast) {
    front_last_node = slow;
    slow = slow->next;
    fast = (fast->next) ? fast->next->next : NULL;
  }
  front_last_node->next = NULL;  // ends the front sublist
  *front = head;
  *back = slow;
}

问题是我没有获得最佳的运行时间,有时甚至是预期的输出。

2 个答案:

答案 0 :(得分:1)

通常,您的代码适用于偶数大小的列表。考虑4个元素A - >的列表。 B - > C - > D - > NULL并查看算法跟踪。

A    slow, fast, head
B
C
D
NULL

A    front_last_node, head
B    slow
C    fast
D
NULL

A    head
B    front_last_node
C    slow
D
NULL fast

然后你删除链接B-> C并返回两个列表:A - > B和C - > D.这正是这个函数的通缉行为,不是吗?

答案 1 :(得分:0)

还有另一种方式;

使用循环计算链表中的元素数量。

如果它的一对 - 第一个列表在head(第一个元素的地址)和i = n / 2个元素之间。第二个列表在i = 0.5n + 1个元素到最后一个元素之间。

否则第一个列表在头部到i = 0.5n + 1个元素之间,第二个列表在i = 0.5n + 2到最后一个之间。

为了方便起见,当你运行循环来计算元素的数量时,使用一个变量来保留最后一个和中间的位置,这样在需要时就可以很容易地使用它们。