简体   繁体   English

反向打印链表

[英]reverse print linked list

my English is not very well, but hope u guys can understand me what i'm trying to say. 我的英语不太好,但希望你们能听懂我想说的话。 So this is the code for linked list, and after run the program and add the information, it can be print at printListStart().Now i having trouble for writing a code at printListEnd(),and i want to show the code from end(reverse). 所以这是链表的代码,运行程序并添加信息后,可以在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()
{

}

Simplest way is to create a doubly-linked list, where each node has a next and previous pointer, where next points to next node (like you are doing now) and previous points to the previous node. 最简单的方法是创建一个双向链接列表,其中每个节点都有一个下一个和上一个指针,下一个指向下一个节点(就像您现在正在做的一样),前一个指向上一个节点。 You will also need pointers to the front and end of the list. 您还需要指向列表开头和结尾的指针。 To print it in reverse, start with pointer to last node and follow the previous pointers instead of next pointers. 要反向打印它,请从指向最后一个节点的指针开始,然后跟随上一个指针而不是下一个指针。

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;

When adding a node to the end, prev for the new node to listend, and set listend to the new node. 将节点添加到末尾时,请先侦听新节点,然后将侦听器设置为侦听新节点。

If you cannot use a doubly-linked list for some reason, your choices are to use a nested loop, or to use recursion. 如果由于某种原因不能使用双向链表,则选择使用嵌套循环或递归。 Both of these solutions are horrible. 这两种解决方案都是可怕的。 Here's the nested loop solution, which is horrible because it runs in O(N^2) time: 这是嵌套循环解决方案,这很可怕,因为它在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;
        }
    }
}

Here's the recursive solution, which is horrible because it wastes stack space in proportion to the length of the list: 这是递归解决方案,这很可怕,因为它浪费了与列表长度成比例的堆栈空间:

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

Sorry but I immediately thought to the recursion. 抱歉,但我立即想到了递归。 Why don't give a chance to this fantastic tecnique? 为什么不给这个神奇的技术一个机会呢? Let me try: 让我尝试:

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

To call the function you need to pass your variable list (the root node of your list). 要调用该函数,您需要传递变量列表(列表的根节点)。

After accept answer 接受答案后

Allocate an array to store the link addresses. 分配一个数组来存储链接地址。 Then print the array elements in reverse order. 然后以相反的顺序打印数组元素。
O(n) time. 准时。

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

This approach does not make use of functional recursion. 此方法不使用功能递归。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM