简体   繁体   English

交换反转c中的链表

[英]Swap reversing a linked list in c

Given a list, I want to reverse the list by swapping the first with the last, second with the second last and so on. 给定一个列表,我想通过将第一个与最后一个交换,第二个与第二个倒数交换,以反转列表,依此类推。

I wrote this function to swap each pair where pos1 and pos2 are the two positions to be swapped. 我写了这个函数来交换每对,其中pos1pos2是要交换的两个位置。

maxPos is the largest of the two positions, node1 and node2 are the two nodes that were found after traversing the list. maxPos是两个位置中最大的一个, node1node2是遍历列表后找到的两个节点。

int swap(struct node *list, int pos1, int pos2) {

    if (node1 != NULL && node2 != NULL) {
        if (prev1 != NULL)
            prev1->next = node2;
        if (prev2 != NULL)
            prev2->next = node1;
        temp        = node1->next;
        node1->next = node2->next;
        node2->next = temp;
        if (prev1 == NULL)
            head = node2;
        else if (prev2 == NULL)
            head = node1;
    }
    return 1;
}

Instead of calling this recursively for each pair, ie. 而不是为每个对递归调用它,即。 (1,n-1) , (2,n-2) , (3,n-3) for which it has to traverse the list every time, I was wondering if there is a way for it to be solved iteratively. (1,n-1)(2,n-2)(3,n-3)每次都必须遍历该列表,我想知道是否有办法迭代地解决它。

Do you really want to swap node contents? 您真的要交换节点内容吗?

You can reverse the list iteratively with a very simple function: 您可以使用一个非常简单的函数来迭代地反转列表:

struct node {
    // whatever payload fields...
    struct node *next;
};

struct node *reverse_list(struct node *list) {
    struct node *last = NULL;
    while (list != NULL) {
        struct node *next = list->next;
        list->next = last;
        last = list;
        list = next;
    }
    return last;
}

When using a list with an anchor element (eg the first element is a node but not used for storing data), you can use 当使用带有锚元素的列表(例如,第一个元素是节点但不用于存储数据)时,可以使用

struct node **list_nth(struct node *node, size_t idx)
{
    for (;idx > 0 && node; --idx)
        node = node->next;

    return node ? &(node->next) : NULL;
}

void list_swap(struct node *head, size_t idx_a, size_t idx_b)
{
    struct node **a = list_nth(head, min(idx_a, idx_b));
    struct node **b = list_nth(head, max(idx_a, idx_b));
    struct node *tmp;

    if (idx_a == idx_b)
        return;

    if (!a || !b)
        abort();

    if ((*a)->next == *b) {
        tmp = *a;

        *a  = *b;
        tmp->next = (*b)->next;
        (*a)->next = tmp;
    } else {
        tmp        = (*a)->next;
        (*a)->next = (*b)->next;
        (*b)->next = tmp;

        tmp = *a;
        *a  = *b;
        *b  = tmp;
    }
}

for the swap operation. 用于交换操作。 But for single linked lists, your reverse operation has a complexity of O(n^2) due to the expensive node lookup. 但是对于单个链表,由于昂贵的节点查找,您的反向操作的复杂度为O(n ^ 2)。

As noted somewhere else, for reversing a list: 如其他地方所述,要反转列表:

  • use a double-linked one 使用双链接的
  • iterate it in reverse with O(n) 用O(n)反向迭代
  • remove the element (O(1)) 删除元素(O(1))
  • append the element to a new head (O(1)) 将元素附加到新的头(O(1))
  • merge the new list into the old one back (O(1)) 将新列表合并到旧列表中(O(1))

You'll have to declare a new method for reversing the whole list that'll be called only once. 您必须声明一个新方法来反转整个列表,该方法将仅被调用一次。 Also you'd better use a doubly-linked list for this problem. 同样,您最好使用双链表来解决此问题。

Node structure: 节点结构:

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

Method: 方法:

void reverse() {

    struct node *temp = head; // assuming you have the head node as a global variable.
    struct node *lastPtr = head;

    for (int i = 0; i < len; i++) { // assuming you have length as a global variable.
        lastPtr = lastPtr->next;
    }

    for (int i = 0; i < len / 2; i++) {
        temp->data += lastPtr->data;
        lastPtr->data = temp->data - lastPtr->data;
        temp->data -= lastPtr->data;
        temp = temp->next;
        lastPtr = lastPtr->prev;
    }
}

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

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