拆分链表

时间:2008-11-27 17:52:49

标签: c data-structures linked-list

为什么拆分列表在此程序中始终为空? (它来自链接列表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;
}

4 个答案:

答案 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]