为什么拆分列表在此程序中始终为空? (它来自链接列表Wikipedia页面上的代码。)
/*
Example program from wikipedia linked list article
Modified to find nth node and to split the list
*/
#include <stdio.h>
#include <stdlib.h>
typedef struct ns
{
int data;
struct ns *next; /* pointer to next element in list */
} node;
node *list_add(node **p, int i)
{
node *n = (node *)malloc(sizeof(node));
if (n == NULL)
return NULL;
n->next = *p; //* the previous element (*p) now becomes the "next" element */
*p = n; //* add new empty element to the front (head) of the list */
n->data = i;
return *p;
}
void list_print(node *n)
{
int i=0;
if (n == NULL)
{
printf("list is empty\n");
}
while (n != NULL)
{
printf("Value at node #%d = %d\n", i, n->data);
n = n->next;
i++;
}
}
node *list_nth(node *head, int index) {
node *current = head;
node *temp=NULL;
int count = 0; // the index of the node we're currently looking at
while (current != NULL) {
if (count == index)
temp = current;
count++;
current = current->next;
}
return temp;
}
/*
This function is to split a linked list:
Return a list with nodes starting from index 'int ind' and
step the index by 'int step' until the end of list.
*/
node *list_split(node *head, int ind, int step) {
node *current = head;
node *temp=NULL;
int count = ind; // the index of the node we're currently looking at
temp = list_nth(current, ind);
while (current != NULL) {
count = count+step;
temp->next = list_nth(head, count);
current = current->next;
}
return temp; /* return the final stepped list */
}
int main(void)
{
node *n = NULL, *list1=NULL, *list2=NULL, *list3=NULL, *list4=NULL;
int i;
/* List with 30 nodes */
for(i=0;i<=30;i++){
list_add(&n, i);
}
list_print(n);
/* Get 1th, 5th, 9th, 13th, 18th ... nodes of n etc */
list1 = list_split(n, 1, 4);
list_print(list1);
list2 = list_split(n, 2, 4); /* 2, 6, 10, 14 etc */
list_print(list2);
list3 = list_split(n, 3, 4); /* 3, 7, 11, 15 etc */
list_print(list3);
list3 = list_split(n, 4, 4); /* 4, 8, 12, 16 etc */
list_print(list4);
getch();
return 0;
}
答案 0 :(得分:5)
temp = list_nth(current, ind);
while (current != NULL) {
count = count+step;
temp->next = list_nth(head, count);
current = current->next;
}
你正在找到正确的项目来开始拆分,但是看看从那时起对temp发生了什么......你只需要分配给temp-&gt; next。
您需要跟踪拆分列表的头部和插入新项目的尾部。
答案 1 :(得分:0)
该计划实际上有不止一个问题。
索引不是解决链接列表内容的本机方式。通常,使用指向节点或迭代器(指向节点的伪装指针)的指针。使用索引,访问节点具有线性复杂度(O(n)
)而不是常量O(1)
。
请注意list_nth
返回指向列表中“实时”节点的指针,而不是副本。通过分配temp->next
中的list_split
,您重新布线原始列表而不是创建新列表(但可能是故意的?)
在list_split
内,temp
永远不会提升,因此循环只会将节点连接到头部而不是尾部。
由于使用list_nth
通过从头开始遍历整个列表来查找节点,list_split
具有二次时间(O(n**2)
)而不是线性时间。最好重写函数迭代列表一次并复制(或重新附加)所需的节点,而不是调用list_nth
。或者,您可以写current = list_nth(current, step)
。
[编辑] 忘了提。由于您正在重新布线原始列表,因此编写list_nth(head, count)
是不正确的:它将在“短路”列表中传输,而不是未经修改的列表。
答案 2 :(得分:0)
你对list_split应返回的内容的描述非常清楚,但目前尚不清楚原始列表应该发生什么。假设它不应该改变:
node *list_split(node *head, int ind, int step) {
node *current = head;
node *newlist=NULL;
node **end = &newlist;
node *temp = list_nth(current, ind);
while (temp != NULL) {
*end = (node *)malloc(sizeof(node));
if (*end == NULL) return NULL;
(*end)->data = temp->data;
end = &((*end)->next);
temp = list_nth(temp, step);
}
return newlist; /* return the final stepped list */
}
(您可能希望将list_insert例程与插入新例程的因素区分开来 在给定位置的节点。 list_add不是很有用,因为它总是添加到 列表的开头。)
答案 3 :(得分:0)
我还注意到,在计算 list_nth 时,您似乎正在跳过列表中的第一条记录。记住是C,我们通常从0开始计数。
绘制一个链接列表图并遵循您的逻辑:
[0]->[1]->[2]->[3]->[4]->[5]->[6]->[7]->[8]->[9]->...->[10]->[NULL]