在不使用指针指针的情况下反转链接列表

时间:2017-07-23 23:36:31

标签: c pointers linked-list

我已使用此代码成功实现了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;

编辑:结构是:

D:\Documents\Everything Programming\_Not Hacking\Bots\Discord Bots\python img recog>imgrecog.py
  File "D:\Documents\Everything Programming\_Not Hacking\Bots\Discord Bots\python img recog\imgrecog.py", line 3
    print(pytesseract.image_to_string(Image.open('C:\Users\[MY NAME]\Desktop\letrs.jpg')))
                                                ^
SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 2-3: truncated \UXXXXXXXX escape

3 个答案:

答案 0 :(得分:6)

您可以通过交换第一个和最后一个节点(浅拷贝)来反转列表,然后反转列表。这样,最后一个节点的 content 将最终出现在头指针已经指向的初始节点中。

这是一个实现:

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;
}

Demo.

答案 1 :(得分:4)

函数有三种主要方式可以为其调用者提供计算值。

  1. 它可以return该值,或包含它的对象,或指向这样一个对象的指针(在最后一种情况下,提供指向的对象超过函数调用)。 / p>

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

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

  4. 还有其他替代方案,主要涉及I / O,但这些方法通常都符合(3)的精神。

    您不得使用(1)。你不能以你提出的方式使用(2)。可能是(3)是预期的答案,但这是丑陋的,真的不应该被推荐。那该怎么办?

    也许你只是咬紧牙关并使用文件范围变量,但是如果你被允许寻求呼叫者的帮助和/或在列表的形式上提出要求那么你有另一种可能性:拥有调用者传递一个指针,该指针在列表反转时不会改变 - 即指向包含指向列表头的指针的结构的指针。然后该函数不需要修改该指针;它通过指向对象返回新的列表头。

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

答案 2 :(得分:0)

看看这个:

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
    }
}