Print a doubly linked list in reverse order?

风格不统一 提交于 2019-12-24 10:49:50

问题


My minimal reproducible example:

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

typedef struct NodeStruct Node;

//struct for each office item
struct NodeStruct {
    int id;
    struct NodeStruct *next;
    struct NodeStruct *prev; //Create doubly linked list node
};

/** Structure for the whole list, including head and tail pointers. */
typedef struct {
    /** Pointer to the first node on the list (or NULL ). */
    Node *head;
    Node *last;
} List;

List *list;

List *makeList();
static void *addRecord(List *list, int newID);
static void printReverse(List *list);

int main(int argc, char **argv) {
    //Create an empty list for you to start.
    list = (List *)makeList();

    addRecord(list, 1);
    addRecord(list, 2);
    addRecord(list, 3);
    addRecord(list, 4);
    addRecord(list, 15);
    printReverse(list);
    return 0;
}

List *makeList() {
    List *list = (List *)malloc(sizeof(List));
    list->head = NULL;
    return list;
}

static void *addRecord(List *list, int newID) {
    //Allocate memory for the node
    Node *new = (Node *)malloc(sizeof(Node)); 

    //Add in data
    new->id = newID; 

    //New node has no next, yet
    new->next = NULL;

    Node **next_p = &list->head;
    while (*next_p) {
        next_p = &(*next_p)->next;
    }
    *next_p = new;

    return EXIT_SUCCESS;
}

static void printReverse(List *list) {
    Node **tail = &list->last;
    printf("LIST IN REVERSE ORDER:\n");

    //Traversing until tail end of linked list
    while (*tail) {
        printf("Item ID: %d\n", (*tail)->id);
        tail = &(*tail)->prev;
    }
}

Input:

1 -> 2 -> 3 -> 4 -> 15

Expected output:

15 -> 4 -> 3 -> 2 -> 1

Actual output:

segmentation fault


EDIT: Set the prev node in the linked list:

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

typedef struct NodeStruct Node;

//struct for each office item
struct NodeStruct {
    int id;
    struct NodeStruct *next;
    struct NodeStruct *prev; //Create doubly linked list node
};

/** Structure for the whole list, including head and tail pointers. */
typedef struct {
    /** Pointer to the first node on the list (or NULL ). */
    Node *head;
    Node *last;
} List;

List *list;

List *makeList();
static void *addRecord(List *list, int newID);
static void printReverse(List *list);

int main(int argc, char **argv) {
    // Create an empty list for you to start.
    list = (List *)makeList();

    addRecord(list, 1);
    addRecord(list, 2);
    addRecord(list, 3);
    addRecord(list, 4);
    addRecord(list, 15);
    printReverse(list);
    return 0;
}

List *makeList() {
    List *list = (List *)malloc(sizeof(List));
    list->head = NULL;
    return list;
}

static void *addRecord(List *list, int newID) {
    //Allocate memory for the node
    Node *new = (Node *)malloc(sizeof(Node)); 

    //Add in data
    new->id = newID; 
    new->prev = NULL;

    //New node has no next, yet
    new->next = NULL;

    Node **next_p = &list->head;
    while (*next_p) {
        next_p = &(*next_p)->next;
    }
    *next_p = new;
    list->last = new;
    new->prev = *next_p;

    return EXIT_SUCCESS;
}

static void printReverse(List *list) {
    Node **tail = &list->last;
    printf("LIST IN REVERSE ORDER:\n");

    //Traversing until tail end of linked list
    while (*tail) {
        printf("Item ID: %d\n", (*tail)->id);
        tail = &(*tail)->prev;
    }
}

With this edit made to addRecord, I keep getting an infinite loop that prints Item ID: 15 over and over again.


回答1:


1) You add (append to be exact, you add it to end) your first node, with a value of 1, and you set head to it. But what about last? Isn't the last node also the first node in your list? Yes it is! Moreover, you set the next pointer to NULL, correct... But what about the prev pointer? Shouldn't it be set to NULL too, since their so no previous node? Yes again.

2) list does not need to be global, and to be honest, it shouldn't be.

3) When you do:

*next_p = new;
new->prev = *next_p;

then you say that the previous node of the newly appended node is the new node. It should be the last, which we know apriori, so we can do:

new->prev = list->last;

just after constructing the node.

4) Furthermore, when you create the empty list, the status should be that both head and last pointers are set to NULL.

5) Finally, you could simplify your print function to not use a double pointer, but just a pointer.

Putting everything together, we get:

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

typedef struct NodeStruct Node;

//struct for each office item
struct NodeStruct {
    int id;
    struct NodeStruct *next;
    struct NodeStruct *prev; //Create doubly linked list node
};

/** Structure for the whole list, including head and tail pointers. */
typedef struct {
  /** Pointer to the first node on the list (or NULL ). */
  Node *head;
  Node *last;
} List;

List *makeList();
static void *addRecordAtEnd(List *list, int newID);
void print(List *list);
void printReverse(List *list);

int main() 
{
  // Create an empty list for you to start.
  List* list = makeList();

  addRecordAtEnd(list, 1);
  addRecordAtEnd(list, 2);
  addRecordAtEnd(list, 3);
  addRecordAtEnd(list, 4);
  addRecordAtEnd(list, 15);
  print(list);
  printReverse(list);
  return 0;
}

List *makeList()
{
  List *list = malloc( sizeof( List ) );
  if(list != NULL)
  {
    list->head = NULL;
    list->last = NULL;
  }
  return list;
}

static void *addRecordAtEnd(List *list, int newID) 
{
  //Allocate memory for the node
  Node *new = malloc(sizeof(Node)); 

  //Add in data
  new->id = newID; 

  new->prev = list->last;
  new->next = NULL;

  list->last = new;

  // if list is empty
  if(!list->head)
  {
    list->head = new;
    return EXIT_SUCCESS;
  }

  Node **next_p = &list->head;
  while (*next_p) {
    next_p = &(*next_p)->next;
  }
  *next_p = new;

  return EXIT_SUCCESS;
}


void print(List *list)
{
  Node *current_node = list->head;
  while (current_node) {
    printf("Item ID: %d\n", current_node->id);
    current_node = current_node->next;
  }
}

void printReverse(List *list)
{
  Node *current_node = list->last;
  printf("LIST IN REVERSE ORDER:\n");

  //Traversing until tail end of linked list
  while (current_node) {
    printf("Item ID: %d\n", current_node->id);
    current_node = current_node->prev;
  }
}

Output (to also check that the next pointers are correctly set):

Item ID: 1
Item ID: 2
Item ID: 3
Item ID: 4
Item ID: 15
LIST IN REVERSE ORDER:
Item ID: 15
Item ID: 4
Item ID: 3
Item ID: 2
Item ID: 1

PS: Do I cast the result of malloc? No!




回答2:


The problem is in function addRecord(): new->prev = *next_p;

next_p is not a pointer to the last node, it is a pointer to the next member of the last node. In this particular case, *next_p has been set to new just before.

It is simpler to not use the double pointer trick for doubly linked lists and just special case the empty list:

static void *addRecord(List *list, int newID) {
    //Allocate memory for the node
    Node *new_node = (Node *)malloc(sizeof(Node)); 

    if (new_node == NULL)
        return EXIT_FAILURE;

    //Add in data
    new_node->id = newID; 
    new_node->next = NULL;
    if (list->head == NULL) {
        new_node->prev = NULL;
        list->head = new_node;
    } else {
        new_node->prev = list->last;
        list->last->next = new_node;
    }
    list->last = new_node;
    return EXIT_SUCCESS;
}

Similarly, the print function can be written without a double pointer:

static void printReverse(List *list) {
    // Traversing until tail end of linked list
    printf("LIST IN REVERSE ORDER:\n");
    for (Node *node = list->last; node; node = node->prev) {
        printf("Item ID: %d\n", node->id);
    }
}

Note that the initialization function must initialize last too for printReverse to handle empty lists correctly:

List *makeList() {
    List *list = (List *)malloc(sizeof(List));
    if (list != NULL) {
        list->head = list->last = NULL;
    }
    return list;
}


来源:https://stackoverflow.com/questions/57232774/print-a-doubly-linked-list-in-reverse-order

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!