反向打印链表

时间:2015-11-19 17:34:56

标签: c linked-list

我的英语不是很好,但希望你们能理解我想说的话。所以这是链表的代码,在运行程序并添加信息之后,可以在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()
{

}

4 个答案:

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

这种方法不使用函数递归。