以相反的顺序打印双向链表?

时间:2019-07-27 13:55:02

标签: c pointers printf nodes doubly-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 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;
    }
}

输入:

  

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

预期输出:

  

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

实际输出:

  

分段错误


编辑:在链接列表中设置prev节点:

#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;
    }
}

addRecord进行此编辑后,我不断获得一个无限循环,可以一遍又一遍地打印Item ID: 15

2 个答案:

答案 0 :(得分:3)

1)您添加(确切地说,将其添加到末尾)第一个值为1的节点,并将其设置为head。但是last呢?您列表中的最后一个节点也不也是第一个节点吗?是的!此外,您将next指针设置为NULL,正确...但是prev指针呢?既然它们也没有以前的节点,也应该不将其设置为NULL吗?再次是。

2)list不必是全球性的,老实说,它不必是全球性的。

3)当您这样做:

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

然后,您说新添加的节点的前一个节点是新节点。它应该是最后一个,我们知道先验,所以我们可以这样做:

new->prev = list->last;

在构造节点之后。

4)此外,当创建空列表时,状态应为头指针和最后一个指针都设置为NULL。

5)最后,您可以简化打印功能,以不使用双指针,而只需使用指针。

将所有内容放在一起,我们得到:

#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;
  }
}

输出(还要检查是否正确设置了下一个指针):

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?不!

答案 1 :(得分:1)

问题出在功能addRecord()中:new->prev = *next_p;

next_p不是指向最后一个节点的指针,它是指向最后一个节点的next成员的指针。在这种特殊情况下,*next_p刚刚被设置为new

对双向链接列表不使用双指针技巧,而在特殊情况下对空列表不使用双指针技巧更简单:

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;
}

类似地,可以在没有双指针的情况下编写打印功能:

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);
    }
}

请注意,初始化功能也必须初始化lastprintReverse才能正确处理空列表:

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