简体   繁体   中英

Swapping nodes in a linked list

I am trying to swap two adjacent nodes in a linked list, and I think I understand the idea of how to do it using a temporary node.

Here is my struct swap function

struct part {
   char* name;
   float price;
   int quantity;
   struct part *next;
};
typedef struct part partType;

partType *swap_node(partType **item) {

  partType *temp;
  temp = *item;
  *item = (*item)->next;
  temp->next = (*item)->next;
  (*item)->next = temp;
  return *item;
}

I cant think of how to make the previous node in the list point to the new swapped node. Do i need another temp variable? Also, how do I account for the case that the two nodes to be swapped are the first two in the list.

From the code, it looks like you want to swap item and item->next.

If you don't have a doubly-linked list, then you need to set linkPtr to head, and then iterate until linkPtr->next == *item. From there, you can start switching between linkPtr, linkPtr->next and linkPtr->next->next.

You also need a separate condition comparing linkPtr to head, and if so, then you need to set head to the new head.

Ignore the answers about doubly-linked lists. To answer your question, you need to think about how you call your function.

Right now, you have a function that takes a pointer to a pointer. It currently points to a node (node A), which in turn points to another node (node B). Imagine this scenario:

partType a, b, c, d;
a->next = &b;
b->next = &c;
c->next = &d;
d->next = NULL;

Now, you want to swap the order of B and C to have A->C->B->D using your function. Well, you'd do:

swap_node(&a->next);

A was pointing to B; now it's pointing to C. As you can see, the "previous" node is already pointing to C, as you expected. In other words, you've already accomplished your goal. Cheers!

Notes: What exactly is happening in your swap function? Let's break it down. First, the parameter you give it is a pointer to a pointer . Those are a bitch to think about because of the wording -- don't let the wording fool you. Just like "rate of change of the rate of change" is a bitch to think about but "acceleration" is much easier. You want to parse it by remembering that the parameter is, first and foremost, a pointer to some data, and your function is going to modify the data that it points to.

So your function gets a pointer to this 'p', which is pointing to a spot in the linked list which (you assume, see PS) points to two nodes (call them X and Y). Diagram:

[p] --> X[next] --> Y[next] --> Z[next]

Your algorithm does:

  1. Make [p] point to Y: *item = (*item)->next
  2. Make X[next] point to Z: temp->next = (*item)->next
  3. Make Y[next] point to X: (*item)->next = temp

So, if you now consider my A, B, C, D example, the linked list was:

A[next] --> B[next] --> C[next] --> D[next] --> NULL

you can see more clearly what pointer I'm passing. It's the location in memory (read: pointer) where A[next] is stored, which your function needs to do the swapping.

Incidentally, another way to code this would be to do:

a->next = swap_node(&a->next);

but don't do that. It's redundant.

PS Have you thought about what happens when you ask to swap the last node in the series? Right now, things explode :P

With data this small, you might as well just swap everything but the next pointers:

partType tmp = *item;
memcpy(item, item->next, offsetof(item, next));
memcpy(item->next, &tmp, offsetof(item, next));

If your data gets too large to do this, you'll need a pointer to the node before the two you want. The nice part is that your fixing of prev 's next pointer acts as a temp variable, letting you not need one.

prev->next = item->next;
item->next = item->next->next;
prev->next->next = item;

Simple way to swap to node... I am not writing actual code. I am just giving you a hint to swap nodes.

[1]->[2]->[3]->[4]

Suppose this is your linked list and you want to swap [2] and [3] .

  1. use loop to reach till [2] . so your temp is at [2] .
  2. Now temp1 = temp->next; Hence temp1 is at [3] .
  3. temp->next = temp1->next;

    temp1->next = temp;

so now temp->next = [4] and temp1->next = [2]

Four easy options:

First option: Keep track of the pointer to prev (probably the direction the assignment is expected to take).

Second option: Implement a doubly linked list so that you can always find the previous node.

Third option: Implement a singly linked list (as your assignment probably calls for), but give each node two pointers: One pointing to 'next', and one pointing to the data payload (which could be just about anything; a struct, an array, or a plain old data type). Then you just swap where the payload pointers point without worrying about 'next' and 'prev'.

A fourth option: Swap the data itself (possibly the direction the assignment is expected to take).

There are use cases for each of the above.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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