【问题标题】:Linked list and pointers链表和指针
【发布时间】:2016-03-26 08:28:21
【问题描述】:

我试图将我在main中的链表地址传递给一个指针,将它传递给一个函数来为其分配内存并遍历下一个节点,同时保持下一个节点的位置而不破坏头节点。

typedef struct {
    int data;
    struct node_list *next;
}node_list;

typedef struct {
    struct node_list *head;
}list;

void insert_list(node_list **c, int num);

void main()
{
    int num;
    list *list_odd = (list*)calloc(1, sizeof(list));
    node_list *c = &list_odd->head;

    while (num != -1)
    {
        if (num % 2)
            insert_list(c, num);
    }
}

void insert_list(node_list **c, int num)
{
    if (*c == NULL)
    {
        *c = (node_list*)malloc(sizeof(node_list)); // it allocates the memory in the right place.
        (*c)->data = num;
        (*c) = (*c)->next; // but this step breaks the starting list pointer
    }
    else
    {
        (*c)->next = (node_list*)malloc(sizeof(node_list));
        (*c)->data = num;
        (*c) = (*c)->next;
    }
}

编辑:我可能没有解释自己,澄清一下:如果我的列表指向链表的开头,而我为它分配内存然后执行 (*c) = (*c)->next,我的头不再指向乞讨。我想要实现的是拥有列表的开头并保存下一个节点的位置。

【问题讨论】:

  • 有问题吗?如果是这样,它是什么?当你调试你的调试器时你发现了什么?
  • @Dannz 编译将发出一条消息,因为使用了类型不兼容的 node_list 和 struct node_list 指针。
  • 如果我的列表指向链表的开头,而我为它分配内存然后执行 (*c) = (*c)->next,我的头不再指向乞讨。我想要实现的是拥有列表的开头并保存下一个节点的位置。
  • @Dannz 另外我认为函数的第一个参数应该是列表。
  • @VladfromMoscow 我可以发送列表并遍历到列表末尾,但这将是 O(n),我认为有可能使 O(1)。

标签: c pointers struct linked-list


【解决方案1】:

我想建议一个双边单链表。

这是一个演示程序。

#include <stdlib.h>
#include <stdio.h>

typedef struct node
{
    int data;
    struct node *next;
} node;

typedef struct list
{
    node *head;
    node *tail;
} list;

int push_back( list *lst, int data )
{
    node *new_node = malloc( sizeof( node ) );
    int success = new_node != NULL;

    if ( success )
    {
        new_node->data = data;
        new_node->next = NULL;

        if ( lst->tail == NULL )
        {
            lst->tail = lst->head = new_node;
        }
        else
        {
            lst->tail = lst->tail->next = new_node;
        }            
    }

     return success;
 }

void display( list *lst )
{
    for ( node *current = lst->head; current != NULL; current = current->next )
    {
        printf( "%d ", current->data );
    }
    printf( "\n" );
}

int main( void )
{
    list lst = { NULL, NULL };

    int data;

    while ( scanf( "%d", &data ) == 1 && data != -1 )
    {
        if ( data % 2 != 0 ) push_back( &lst, data );
    }

    display( &lst );

    return 0;
}

如果要输入这个数字序列

0 1 2 3 4 5 6 7 8 9 -1

那么输出将是

1 3 5 7 9 

将新节点添加到列表末尾的复杂度是 O(1)。

【讨论】:

  • 您费力地检查了malloc 的返回码并从push_back 中返回它,但如果它真的失败了,程序将继续运行并崩溃;)
  • @Pod 这是一个演示程序,仅用于演示该方法。如果您愿意,可以在程序中添加任何额外的检查和方法。
  • @Pod 顺便说一句,即使实际上没有添加任何节点,程序也不会崩溃。该列表将是空的。
【解决方案2】:

我想要实现的是拥有列表的开头并保存下一个节点的位置。

我不完全确定您要做什么,所以我制作了一个等效程序。如果您发现这种添加到列表的方式太慢,则需要更改程序以保留 {head, tail} 对或将项目添加到列表的前面。从您的文字看来,您正试图保持头部不变——因此 {head,tail} 对可能是最好的。

#include <stdlib.h>  //added
#include <stdio.h>  //added
#include <assert.h>

typedef struct node_list_t {   //changed
    int data;
    struct node_list_t *next;   //changed
} node_list;

typedef struct list_t { //gave the struct a tag
    node_list *head;    //use the typedef name, not the struct name
}list;

void insert_list(list *my_list, int num);

void main()
{
    int num = 0; // initialised
    list my_list = {0}; // changed to be on stack. Could be calloc'd if you like
    node_list* printer;

    while (num != 50) //changed limit
    {
        if (num % 2)
        {
            // we're just passing in the list
            insert_list(&my_list, num);
        }

        num += 1;  //actually incrementing number. :)
    }


    for (printer = my_list.head;
            printer;
                printer = printer->next)
    {
        printf("%d\n", printer->data);
    }
}

void insert_list(list *my_list, int num)
{
    node_list *c = (node_list*) calloc(1, sizeof(node_list));
    c->data = num;

    assert(!c->next);

    if (!my_list->head)
    {
        // if the head is not initialised, then make C the head
        my_list->head = c;
    }
    else
    {
        // otherwise stick it on the end of the list.
        node_list *p;
        for (p = my_list->head;
                p->next;
                    p = p->next)
        {
            //do nothing
        }
        p->next = c;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-29
    • 2011-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-11
    • 1970-01-01
    相关资源
    最近更新 更多