我的英语不是很好,但希望你们能理解我想说的话。所以这是链表的代码,在运行程序并添加信息之后,可以在printListStart()打印。现在我在printListEnd()上编写代码时遇到了麻烦,我想从末尾显示代码(反向)。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <conio.h>
//function prototype
void addToStart(); //add node to beginning of linked list
void addToEnd(); //add node to end of linked list
void removeNodeAt(); //remove node that matches element entered
void printListStart(); //print nodes from start
void printListEnd(); //print node from end
void startlist(); //create NULL list
void menu(); //selection
//global variables
int option, number;
char name[20], gender[10],address[50],description[50];
//declare structure for node
struct node
{
char customer_name[20];
int customer_number;
char gender_[10];
char customer_address[50];
char order_description[50];
struct node *next;
}*newnode, *list, *prev, *temp, *tmpdisplay;
void main()
{
startlist(); //function call to create empty list
do
{
menu(); //function call to show menu
switch (option)
{
case 1: system("cls"); addToStart(); break;
case 2: system("cls"); addToEnd(); break;
case 3: system("cls"); removeNodeAt(); break;
case 4: system("cls"); printListStart(); break;
case 5: system("cls"); printListEnd(); break;
case 6: exit(0);
default:
printf("Invalid Option");
getch();
}
} while (option != 6);
}//end main
void startlist()
{
list = NULL; //create empty list
}
void menu()
{
printf("***LINKED LIST***\n\n");
printf(" 1. Add New Node At Start\n");
printf(" 2. Add New Node At End\n");
printf(" 3. Remove Node\n");
printf(" 4. Print Linked List From Start\n");
printf(" 5. Print Linked List From End\n");
printf(" 6. Quit\n");
printf("\nSelect a task: "); //allow user to select choice
scanf("%d", &option);
}
void addToStart()
{
newnode = (struct node*) malloc(sizeof(struct node)); //allocates memory space for new node
printf("Enter the customer name:\n");
scanf("%s", &name);
printf("Enter then customer number:\n");
scanf("%d", &number);
printf("Enter the Oder Description:\n");
scanf("%s", &description);
printf("Enter the Gender:\n");
scanf("%s", &gender);
printf("Enter the Customer Address:\n");
scanf("%s", &address);
newnode->customer_number = number;
strcpy(newnode->customer_name, name); //using stringcopy to copy name to customer_name in node
strcpy(newnode->order_description, description); //using stringcopy to copy transdes to transaction_description in node
strcpy(newnode->gender_, gender);
strcpy(newnode->customer_address, address);
newnode->next = NULL; //set node pointer to NULL
if (list == NULL)
list = newnode; //if list is empty, node is assigned to list
else
{
newnode->next = list; //if list not empty, newnode pointer equals to list first node
list = newnode; //assign newnode to list, newnode is at the start of the list
}
}
void addToEnd()
{
newnode = (struct node*) malloc(sizeof(struct node)); //allocate new memory space for new node
printf("Enter the customer name:\n");
scanf("%s", &name);
printf("Enter then customer number:\n");
scanf("%d", &number);
printf("Enter the Oder Description:\n");
scanf("%s", &description);
printf("Enter the Gender:\n");
scanf("%s", &gender);
printf("Enter the Customer Address:\n");
scanf("%s", &address);
newnode->customer_number = number;
strcpy(newnode->customer_name, name);
strcpy(newnode->order_description, description);
strcpy(newnode->gender_, gender);
strcpy(newnode->customer_address, address);
newnode->next = NULL;
if (list == NULL)
list = newnode; //if list is empty, assign newnode to list as first node
else
{
temp = list; //list not empty, assign temp as list
while (temp->next != NULL) //while pointer does not point to NULL/empty
{
temp = temp->next; //move to subsequent node
}
temp->next = newnode; //loop exits when last node is reached, last node's pointer points to newnode
}
}
void removeNodeAt()
{
printf("Enter customer number to delete: \n");
scanf("%d", &number);
if (list == NULL) //check if list is empty
printf("\n\nLIST IS EMPTY\n\n");
//if list not empty, match number to cust_no in first node
else if (number == list->customer_number)
{
list = list->next; //match found, first node is skipped (deleted)
}
else //match not found in first node, move to subsequent nodes
{
temp = list; //assign temp as list
while (temp->customer_number != number)
{
//if match not found
prev = temp; //prev is pointing to linked list
temp = temp->next;//temp is pointing to next node
}
printf("Node deleted:");
printf("\n%s\n", prev->customer_name);
printf("%d\n", prev->customer_number);
printf("%s\n\n", prev->gender_);
prev->next = prev->next->next; //match found, skip/jump the node (delete)
}
}
void printListStart()
{
if (list == NULL)
printf("\n\nLIST IS EMPTY\n\n");
else
{
tmpdisplay = list;
while (tmpdisplay != NULL)
{
printf("\n%s\n", tmpdisplay->customer_name);
printf("%d\n", tmpdisplay->customer_number);
printf("%s\n", tmpdisplay->gender_);
printf("%s\n", tmpdisplay->order_description);
printf("%s\n", tmpdisplay->customer_address);
tmpdisplay = tmpdisplay->next;
}
}
}
void printListEnd()
{
}
答案 0 :(得分:2)
最简单的方法是创建一个双向链表,其中每个节点都有一个下一个和前一个指针,其中下一个指向下一个节点(就像你现在正在做的那样)和前一个点指向前一个节点。您还需要指向列表前端和末尾的指针。要反向打印,请从指向最后一个节点的指针开始,然后按照前面的指针而不是下一个指针。
struct node
{
char customer_name[20];
int customer_number;
char gender_[10];
char customer_address[50];
char order_description[50];
struct node *next;
struct node *prev;
}*newnode, *list, *prev, *temp, *tmpdisplay, *listend;
在结尾添加节点时,新侦听节点的prev,并将侦听设置为新节点。
答案 1 :(得分:1)
如果由于某种原因无法使用双向链表,则可以选择使用嵌套循环,还是使用递归。这两种解决方案都很糟糕。这是嵌套循环解决方案,这很糟糕,因为它在O(N ^ 2)时间内运行:
void printListEnd()
{
struct node *end;
if (list == NULL)
printf("\n\nLIST IS EMPTY\n\n");
else
{
end = NULL;
while (end != list)
{
tmpdisplay = list;
while (tmpdisplay->next != end)
tmpdisplay = tmpdisplay->next;
printf("\n%s\n", tmpdisplay->customer_name);
printf("%d\n", tmpdisplay->customer_number);
printf("%s\n", tmpdisplay->gender_);
printf("%s\n", tmpdisplay->order_description);
printf("%s\n", tmpdisplay->customer_address);
end = tmpdisplay;
}
}
}
这是递归解决方案,这很糟糕,因为它会浪费堆栈空间与列表长度成比例:
static void printListEndRecurse(struct node *list)
{
if (list->next)
printListEndRecurse(list->next);
tmpdisplay = list;
printf("\n%s\n", tmpdisplay->customer_name);
printf("%d\n", tmpdisplay->customer_number);
printf("%s\n", tmpdisplay->gender_);
printf("%s\n", tmpdisplay->order_description);
printf("%s\n", tmpdisplay->customer_address);
}
void printListEnd()
{
if (list == NULL)
printf("\n\nLIST IS EMPTY\n\n");
else
printListEndRecurse(list);
}
答案 2 :(得分:1)
抱歉,我立刻想到了递归。为什么不给这个梦幻般的tecnique机会呢?让我试试:
void printListEnd(struct node *myList)
{
if (myList != NULL) {
printListEnd(myList->next);
printf("\n%s\n", myList->customer_name);
printf("%d\n", myList->customer_number);
printf("%s\n", myList->gender_);
printf("%s\n", myList->order_description);
printf("%s\n", myList->customer_address);
}
}
要调用函数,您需要传递变量列表(列表的根节点)。
答案 3 :(得分:0)
接受回答后
分配数组以存储链接地址。然后以相反的顺序打印数组元素 O(n)时间。
// Find size
size_t n = 0;
struct node *p = myList;
while (p) {
p = p->next;
n++;
}
// Build array
struct node **list = malloc(sizeof *list * n);
if (list) {
struct node **walker = list;
p = myList;
while (p) {
*walker = p;
walker++;
p = p->next;
}
// Print list
while (walker != list) {
walker--;
print_list(*walker);
}
free(list);
list = NULL;
}
这种方法不使用函数递归。