我的最小可重复示例:
#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
。
答案 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
答案 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);
}
}
请注意,初始化功能也必须初始化last
,printReverse
才能正确处理空列表:
List *makeList() {
List *list = (List *)malloc(sizeof(List));
if (list != NULL) {
list->head = list->last = NULL;
}
return list;
}