繁体   English   中英

反向链接列表,而无需使用指针

[英]Reverse a linked list without using a pointer to pointer

我已经使用以下代码成功实现了2指针解决方案:

void list_reverse(t_list **begin_list)
{
    t_list *new_root;
    t_list *root;
    t_list *next;

    new_root = 0;
    root = *(begin_list);
    while (root)
    {
        next = root->next;
        root->next = new_root;
        new_root = root;
        root = next;
    }
    *begin_list = new_root;
}

哪个工作正常-至少根据我的测试。 现在,我想尝试仅使用单个指针来反向链接列表,而没有return ,所以我尝试将代码转换为void list_reverse(t_list *begin_list) ,但是*begin_list = new_root当然不起作用,因为我不能更改begin_list 其余的似乎工作。

如何在没有双指针的情况下修改begin_list

编辑:结构是:

typedef struct  s_list
{
    struct s_list   *next;
    void            *data;
}               t_list;

您可以通过交换第一个节点和最后一个节点(浅副本)来反转列表,然后反转列表。 这样,最后一个节点的内容将最终到达头指针已经指向的初始节点。

这是一个实现:

void swap(struct node *a, struct node *b) {
    struct node tmp = *a;
    *a = *b;
    *b = tmp;
}

void reverse(struct node *h) {
    // Null list and single-element list do not need reversal
    if (!h || !h->next) {
        return;
    }
    // Find the last node of the list
    struct node *tail = h->next;
    while (tail->next) {
        tail = tail->next;
    }
    // Swap the tail and the head **data** with shallow copy
    swap(h, tail);
    // This is similar to your code except for the stopping condition
    struct node *p = NULL;
    struct node *c = tail;
    do {
        struct node *n = c->next;
        c->next = p;
        p = c;
        c = n;
    } while (c->next != tail);
    // h has the content of tail, and c is the second node
    // from the end. Complete reversal by setting h->next.
    h->next = c;
}

演示

函数可以通过三种主要方式将计算值提供给其调用方。

  1. 它可以return该值,或者包含该值的对象,或者指向该对象的指针(在最后一种情况下,所指向的对象要比函数调用的寿命更长)。

  2. 它可以通过调用者提供的指针来修改对调用者可见的对象。

  3. 它可以将计算出的值记录在调用者可见的文件范围变量中。

还有其他选择,主要涉及I / O,但通常符合(3)的精神。

您不得使用(1)。 您不能以建议的方式使用(2)。 可能是(3)是预期的答案,但这很丑陋,实际上不建议这样做。 那么该怎么办?

也许您只是硬着头皮使用了一个文件作用域变量,但是如果您被允许争取呼叫者的帮助和/或对列表的形式提出要求,那么您还有另一种可能性:让呼叫者通过反向列表时不会改变的指针-即,指向包含列表头指针的结构的指针。 然后,该函数不需要修改该指针。 它通过指向的对象返回新的列表头。

通常情况下,这种情况会使用一种代表整个列表的单独结构类型来进行。 但是,如果想一会儿,您将意识到您现有的列表节点类型已经具有合适的形式。 如果您无法引入新的结构,则可以使用现有的结构-只需将列表中的第一个节点视为其余元素上的不承载数据的句柄即可。 这有时被称为虚拟头节点,并且使用一个头节点的列表在许多方面提供了更简单的功能实现。

看看这个:

void reverse(struct node* head) {
    struct node *curr=head; 
    struct node *next=NULL;
    struct node *prev=NULL; 
    while(curr) { 
        next=curr->next; //we're basically stashing the next element
        curr->next=prev; //setting next pointer to the previous element
        prev=curr; //previous is now current
        curr=next; //and updating the current from the stashed value
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM