简体   繁体   中英

how to print out a singly linked list in reverse order?

struct node
{
  int info;
  struct node *next;
};
typedef struct node node;

void *printRev(node *head){
      int count=0;
      int i;
      node *beforeFin;
      node *tempHead;
      tempHead = head;

      while(tempHead->next != NULL){
          count++;
          tempHead->next = tempHead->next->next; //LAST ITERATION SHOULD BE AT THE END OF LIST
      }
      printf("COUNT IS: %d\n", count);
      for(i = 0; i <= count; i++){
        beforeFin = Prev(head, tempHead->next);
        printf("%d", beforeFin->info);
      }
      printf("\n");
    }

As of now this prints out:

COUNT IS: 3
Segmentation fault (core dumped)

Prev returns a pointer to the node before the given pointer ( tempHead->next ) my intention was for this to print out the singly linked list in reverse order using the for loop above. So the ->info of the given node should return 5 in the example below (after the first iteration).

Before the printf that prints the count, tempHead->next should point to the final node.

Right now I am passing in 2 3 5 4 and this is giving me the count before the 4. Id like for this to print out 4 5 3 2

I would appreciate any help given, I am a beginner as you might be able to tell. Thank you all in advance!

I could do this using recursion but I'd like to learn figure out this method.

To print a single linked list in reverse order you can use a recursive function. You have to step into the recursion to the end and print the elements of the list right before you leave the recursion function:

void printReverse(node *act)
{
    if ( act == NULL )          // terminate if end of list is reached
        return;

    printRev( act->next );      // print next node 
    printf( "%d ", act->info ); // print this node
}

If you do not want to use recursion, you can of course reverse the list, then print the list and finally reverse it again.

Reversing a list is not difficult. Traverse through the list, take each element and reorder it in front of the head of the list.

node * reverse(node *head)
{
  node *act, *prev;
  if ( head == NULL )
      return;

  prev = head;
  act = head->next;
  while ( act != NULL )
  {
      prev->next = act->next;
      act->next = head;
      head = act;
      act = prev->next;
  }
  return head;
}

void printReverse(node *head)
{
    node *act;

    act = reverse(head);
    while ( act != NULL )
    {
      printf( "%d ", act->info ); // print this node
      act = act->next;
    }
    reverse(head);
}

As you want to avoid recursion, you need to reverse the list first. I see some attempt in the original code but it doesn't look correct. Try the following:

node *current = head;
if (current != NULL) {
    node *prev = NULL;
    for (node *next = current->next; ; next = (current = next)->next) {
        current->next = prev;
        prev = current;
        if (next == NULL)
            break;
    }
}

Then current will point to the head of the list and you can traverse using the next link over the list. Note that it will modify your original list but this is expected as I understood the original requirement.

The issue with the recursive algorithm is that, if you're a bit paranoid like me, the list could be large enough to cause the recursive calls to sum up and overflow the stack. If the list is from some user input then this could be used for a denial of service attack. Thus I see two reasonable choices:

  1. Create a reversed copy of the list and print that.
  2. Reverse the list in place, print it, possibly reverse it back.

The later is interesting if you're working in a memory constrained setting or with large lists.

#include <stdio.h>
#include <assert.h>
#include <stdlib.h>

struct node {
  int value;
  struct node * next;
};

void reverse_inplace (struct node ** list) {
  assert(list != NULL);
  struct node * follow = NULL, * lead = *list;
  while (lead != NULL) {
    struct node * next = lead->next;
    lead->next = follow;
    follow = lead;
    lead = next;
  }
  *list = follow;
}

void print (struct node const * head) {
  printf("( ");
  while (head) {
    printf("%d ", head->value);
    head = head->next;
  }
  printf(")");
}

void link (struct node * array, size_t count) {
  struct node * follow = NULL;
  while (count-->0) {
    array[count].next = follow;
    follow = &(array[count]);
  }
}

void fill (struct node * list, int value, int const step) {
  while (list != NULL) {
    list->value = value;
    value += step;
    list = list->next;
  }
}

int main () {
  size_t const sizes[] = {1, 2, 6};
  size_t const num =
    sizeof(sizes) / sizeof(sizes[0]);
  size_t caseId = 0;
  for (; caseId < num; ++caseId) {
    struct node * head =
      malloc(sizeof(*head) * sizes[caseId]);
    printf("Case %zu: List of size %zu\n",
      caseId, sizes[caseId]);
    link(head, sizes[caseId]);
    fill(head, caseId, caseId);
    printf("  initial: ");
    print(head);
    printf(" \n");
    reverse_inplace(& head);
    printf(" reversed: ");
    print (head);
    printf(" \n");
    reverse_inplace(& head);
    free(head);
  }
  printf("Case %zu: empty list \n", caseId);
  struct node * head = NULL;
  printf("  initial: ");
  print(head);
  printf(" \n");
  reverse_inplace(& head);
  printf("  reversed: ");
  print(head);
  printf(" \n");
  return 0;
}

( Live on ideone )

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