【问题标题】:printing linked list from beginning从头打印链表
【发布时间】:2010-07-28 11:19:44
【问题描述】:

我从维基百科获得了链接列表的代码 (http://en.wikipedia.org/wiki/Linked_list)。

但它以相反的顺序打印结果 (5 4 3 2 1 )。如何从头开始打印(1 2 3 4 5)。

【问题讨论】:

  • 您在看哪个代码示例?我认为您误解了插入,而不是印刷。
  • 那是一个包含大量代码示例的长页面。发布您遇到问题的具体例程。
  • 考虑到问题标记为“C”,C 代码示例将是要查看的。
  • wiki 上的示例具有误导性:list_add 实际上是“在开头插入”,而不是直觉所暗示的“添加到结尾”。

标签: c linked-list


【解决方案1】:

我假设您在“语言支持”中谈论 C 实现。

它不会以相反的顺序打印。这是因为元素被插入到列表的头部,所以插入 1、2、3 会导致列表包含 3、2、1。

这是因为列表是由它的头部表示的,所以它在头部插入比在尾部插入更快。要在尾部插入,您必须遍历整个列表。这使得插入 O(n) 而不是 O(1)。

由于这是一个单链表,所以不能按其他顺序打印,因为只能往前走。

【讨论】:

  • 如果我想插入 O(n) 怎么做?我不擅长指针:(
  • @Guru:循环遍历列表,直到到达下一个元素是 NULL 指针的位置。然后只需将该指针设置为您要插入的元素。
  • 注意:这是一个 LIFO(后进先出)设置,而不是 FILO(先进后出)设置。有点像一堆盘子。底部的盘子必须等待其他盘子弹出才能访问。
  • @Paul Dragoonis:当您说 FILO 时,您的意思是 FIFO。 FILO 和 LIFO 一样
  • 是的,我愿意。我认为它在我的脑海中要么是“堆栈”,要么是“队列”。要么是一堆盘子,要么是在商店里排队。
【解决方案2】:

看下面的例子:

/****************************************************************/
/*  Function: Add an element to our list                        */
/*                                                              */
/*   Parameters: **p is the node that we wish to insert at.     */
/*               if the node is the null insert it at the beginning    */
/*               Other wise put it in the next space                   */


LLIST *list_add(LLIST **p, int i)
{
    if (p == NULL)           /*checks to see if the pointer points somewhere in space*/
        return NULL;

    LLIST *n = malloc(sizeof(LLIST));   /* creates a new node of the correct data size */
    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;
}
当您调用list_add 时,

元素被添加到链表的开头。这是出于效率原因;你不必横穿整个链表来插入一个元素(如果你想追加,你必须这样做)。

要反向打印,您可以使用递归,构建自己的堆栈(这是盲人的递归),或者反向重新创建列表。递归版本:

void list_print_reverse(LLIST *n)
{
    if (n == NULL)
    {
        printf("list is empty\n");
        return;
    }

    if (n->next != NULL)
    {
        list_print_reverse(n->next);
    }

    printf("print %p %p %d\n", n, n->next, n->data);
}

【讨论】:

  • 谢谢 :) 而在 list_remove 中,它只删除了第一次出现的数据,我要怎么做才能删除所有出现的数据?
  • 您必须遍历整个列表并逐个删除 1
  • //(如果你想追加,你必须这样做)。抱歉,我是指针的初学者 :(。如果我想追加如何做到这一点?
  • @Guru,在链表中找到最后一个元素,并将新节点分配给last_element->next。 (确保新节点的->next 是NULL!)
  • 正如我所说,我不擅长指针。你能详细解释一下如何遍历到最后一个元素吗?
【解决方案3】:

那是因为列表的构造方式。

要反向打印,只需递归到最后一个条目并从那里打印。

【讨论】:

  • 只是祈祷列表不会太长,否则你会溢出堆栈。
  • 如果您要打印 25 000 个或更多条目,我会更担心... :)
【解决方案4】:

列表的打印顺序是元素在列表中出现的顺序。您可以使用递归以相反的顺序(即插入元素的顺序)打印它。以下代码将以相反的顺序打印列表

void list_print(LLIST *n) {
如果 (n == NULL)
{
printf("列表为空\n");
返回;
}
}

void print_recursive(LLIST *n) {
如果(n->下一个==NULL)
printf("%d\n",n->数据);
其他
print_recursive(LLIST n->next);
}

【讨论】:

  • 超级,您刚刚“复制”了上一个答案!我怎么没想到呢?
  • 我没有复制它。当我开始输入这个答案时不在这里。
【解决方案5】:

我有一个使用递归反向打印字符串的程序。你能用你的链表作为它的输入吗?

void reversePrint(char *str)
{
if(*str == '\0')
return;
reversePrint(str+1);
printf("%c",*str);
}
int main()
{
char *input;
input = malloc(10);
strcpy(input,"wolfrevo");
reversePrint(input);
}

我可以自己更改它,但希望这对你来说是一个很好的练习。

提示:

  1. 传递链表而不是字符串 // 也改变原型
  2. 检查列表是否为 NULL
  3. 通过传递链表的下一个元素进行递归
  4. 打印列表中的数据而不是字符串

【讨论】:

    【解决方案6】:

    你也可以试试双链表。基本上,您有一个指向前一个元素的附加指针

    typedef struct node {
        int data;
        struct node *next;     /* pointer to next element in list */
        struct node *previous; /* pointer to previous element in list */
    } node;
    
    typedef struct list {
        node *head;            /* first element in list */
        node *tail;            /* last element in list */
    } list;
    

    然后您可以从头部和/或尾部打印列表。

    【讨论】:

      猜你喜欢
      • 2021-02-18
      • 2023-03-28
      • 1970-01-01
      • 2023-02-25
      • 2016-10-13
      • 2012-08-15
      • 1970-01-01
      • 2013-05-10
      相关资源
      最近更新 更多