Moving an element in a linked list Given I have a linked list, and I want to move a given node to the end of the list, is there a more elegant way of doing this, than what I've done here?

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;

typedef struct node {
  int val;
  struct node *next;
} node_t;

void insert(node_t **head, int val)
{
  node_t *new_node = malloc(sizeof(node_t));
  node_t *tmp;

  new_node-&gt;val = val;
  new_node-&gt;next = NULL;

  // Empty list?
  if(*head == NULL) {
    *head = new_node;
    return;
  }

  tmp = *head;

  while(tmp-&gt;next != NULL)
    tmp = tmp-&gt;next;

  tmp-&gt;next = new_node;
}

void movetoend(node_t **head, int val)
{
  node_t *curr;
  node_t *tmp = NULL;
  node_t *old = NULL;

  // Find val in list
  for(curr = *head; curr != NULL; old = curr, curr = curr-&gt;next) {
    if(curr-&gt;val == val) {
      // Matched node is the only one in the list, don't do anything
      if(curr-&gt;next == NULL)
        return;

      // Matched node is first, set next to jump over
      if(old == NULL)
        *head = curr-&gt;next;

      // Matched node is in the middle, set next to jump over
      else
        old-&gt;next = curr-&gt;next;

      // Set a pointer to matched node for later use
      tmp = curr;

      // Loop through the rest of the list
      // "old" will have the pointer to last node
    }
  }

  // No matches?
  if(tmp == NULL)
    return;

  // Terminate list
  tmp-&gt;next = NULL;

  // Append matched node
  old-&gt;next = tmp;
}

void print(node_t *head)
{
  while(head) {
    printf("%d\n", head-&gt;val);
    head = head-&gt;next;
  }
}

int main()
{
  node_t *head = NULL;

  insert(&amp;head, 10);
  insert(&amp;head, 20);
  insert(&amp;head, 30);
  movetoend(&amp;head, 10);
  print(head);

  return 0;
}


EDIT: Added comments, modified movetoend function a bit slimmer.
There's more elegant ways, although not necessarily more efficient. The common idiom for fiddling with this kind of linked list in C is to add one more layer of indirection and fiddle with pointers-to-node-pointers, like this:

void insert(node_t **head, int val)
{
    node_t *new_node = malloc(sizeof(node_t));
    new_node-&gt;val = val;
    new_node-&gt;next = NULL;

    node_t **ptmp = head;
    while (*ptmp != NULL) {
        ptmp = &amp;(*ptmp)-&gt;next;
    }
    *ptmp = new_node;
}


Given that example, I think you can figure out how to rewrite movetoend in just a few additional lines: much shorter than the page of code you have now.

However, whether this will be equally fast depends on your compiler and optimization levels. When in doubt, check the assembly code! If you see a lot of additional memory loads in the inner loop, that's a bad sign.

In C++, but I think not in C yet, you could eliminate even the appearance of extra memory loads by doing

void insert(node_t **head, int val)
{
    node_t *new_node = malloc(sizeof(node_t));
    new_node-&gt;val = val;
    new_node-&gt;next = NULL;

    node_t **ptmp = head;
    while (node_t tmp = *ptmp) {
        ptmp = &amp;tmp-&gt;next;
    }
    *ptmp = new_node;
}