以相反的顺序打印双向链表?
Print a doubly linked list in reverse order?
我的最小可重现示例:
#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
实际输出:
segmentation fault
编辑:在链表中设置 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
。
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? 没有!
问题出在函数 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;
}
同样,print函数也可以不用双指针来写:
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;
}
我的最小可重现示例:
#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
实际输出:
segmentation fault
编辑:在链表中设置 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
。
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? 没有!
问题出在函数 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;
}
同样,print函数也可以不用双指针来写:
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;
}