【问题标题】:sorting a linked list using another list使用另一个列表对链表进行排序
【发布时间】:2015-04-05 23:04:16
【问题描述】:

所以我试图对一个整数链表进行排序,但似乎找不到正确的方法,我的想法是采用无序列表,从中找到最大值,然后将其放入另一个列表.由于我不相信我可以从原始列表中删除节点而不将其进行双重链接,因此我计划将列表 1 中的节点设为零值,从而将其状态删除为最大值。因此,我打算运行它一定次数,每次都找到下一个最大值,直到列表 1 全为 0,并且列表 2 是列表 1 曾经的有序版本。我已经创建了一个函数来执行此操作,但它似乎不起作用,虽然我找不到问题。

函数

#include <stdio.h>
#include <stdlib.h>
#include "functions.h"

struct num_node *create(struct num_node *list, int x){
    struct num_node *current;

    if (list == NULL){
        list = (struct num_node*)malloc(sizeof(struct num_node));
        list->num = x;
        list->next = NULL;
        return(list);
    }
    else{
        current = (struct num_node *)malloc(sizeof(struct num_node));
        current->num = x;
        current->next = list;
        return(current);
    }
} 

void print_nums(struct num_node *list) {

    struct num_node *current;
    for (current = list; current != NULL; current = current->next)
        printf("%d\t", current->num);

}

struct num_node *sort_nums(struct num_node *list1, struct num_node *list2){
    struct num_node *current;
    struct num_node *large = list1;

    for (int i = 0; i < 25; i++){
        for (current = list1; current != NULL; current = current->next){
            if (current->num > large->num){
                large = current;
            }
        }
        create(list2, large->num);
        large->num = 0;
        return(list2);
    }
}

int sum(struct num_node *list){
    int total = 0;
    struct num_node *current;
    for (current = list; current != NULL; current = current->next){
        total = total + current->num;
    }

    return total;
}

float average(struct num_node *list){
    float total = 0;
    float count = 0;
    struct num_node *current;
    for (current = list; current != NULL; current = current->next){
        total = total + current->num;
        count++;
    }
    return total / count;
}

主要

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#include "functions.h"

int main(){
    struct num_node *head = NULL;
    struct num_node *new_head = NULL;

    srand(time(NULL));

        for (int i = 1; i <= 25; i++){
            int x = rand() % 100;
            head = create(head, x);
        }

        print_nums(head);

        sort_nums(head, new_head);

        printf("\n");
        printf("\n");
        print_nums(new_head);

        printf("\n");
        printf("\n");
        printf("The total of all numbers is: ");
        printf("\t%d\n", sum(new_head));

        printf("The average of the numbers is: ");
        printf("\t%.3f\n", average(new_head));


}

【问题讨论】:

  • “因为我不相信我可以从原始列表中删除节点而不将它进行双向链接”实际上您也可以删除单链表中的节点,您只需要有一个参考到它的前身。

标签: c list sorting


【解决方案1】:

回到最初的想法,示例代码通过查找最大节点对链表进行排序,然后将其从原始列表(原始列表的左侧)中删除并将该节点插入新列表的前面。请注意,面向合并的算法会快得多。

NODE * SortList(NODE * pList)
{
NODE * pNew = NULL;                     /* sorted list */
NODE **ppNode;                          /* ptr to ptr to node */
NODE **ppLargest;                       /* ptr to ptr to largest node */
NODE * pLargest;                        /* ptr to largest node */
    while(pList != NULL){               /* while list not empty */
        ppLargest = &pList;             /*  find largest node */
        ppNode = &((*ppLargest)->next);
        while(NULL != *ppNode){
            if((*ppNode)->data > (*ppLargest)->data)
                ppLargest = ppNode;
            ppNode = &((*ppNode)->next);
        }
        pLargest = *ppLargest;          /* move node to new */
        *ppLargest = pLargest->next;
        pLargest->next = pNew;
        pNew = pLargest;
    }    
    return(pNew);
}

【讨论】:

    【解决方案2】:

    你从sort_nums过早返回:

    struct num_node *sort_nums(struct num_node *list1, struct num_node *list2){
        struct num_node *current;
        struct num_node *large = list1;
    
        for (int i = 0; i < 25; i++){
            for (current = list1; current != NULL; current = current->next){
                if (current->num > large->num){
                    large = current;
                }
            }
            create(list2, large->num);
            large->num = 0;
            return(list2);   // This just adds the largest item to list2
        }
    }
    

    你需要:

    struct num_node *sort_nums(struct num_node *list1, struct num_node *list2){
        struct num_node *current;
        struct num_node *large = list1;
    
        for (int i = 0; i < 25; i++){
            for (current = list1; current != NULL; current = current->next){
                if (current->num > large->num){
                    large = current;
                }
            }
            list2 = create(list2, large->num);
            large->num = 0;
        }
        return(list2);
    }
    

    另外,您没有在 main 中使用 sort_nums 的返回值。你有:

    sort_nums(head, new_head);
    

    你需要:

    new_head = sort_nums(head, new_head);
    

    简化create

    由于您将项目添加到create 的列表中,因此可以简化为:

    struct num_node *create(struct num_node *list, int x){
       struct num_node *current = malloc(sizeof(struct num_node));
       current->num = x;
       current->next = list;
       return(current);
    } 
    

    简化sort_nums

    您还可以简化sort_nums。你不需要第二个参数。您可以使用:

    struct num_node *sort_nums(struct num_node *list1){
       struct num_node *list2 = NULL;
       struct num_node *current;
       struct num_node *large = list1;
       int i;
    
       for (i = 0; i < 25; i++){
          for (current = list1; current != NULL; current = current->next){
             if (current->num > large->num){
                large = current;
             }
          }
          list2 = create(list2, large->num);
          large->num = 0;
       }
       return(list2);
    }
    

    当然,你必须改变在 main 中使用它的方式。

    new_head = sort_nums(head);
    

    【讨论】:

    • 我以前也是这样,它给了我完全相同的结果,我刚刚复制并粘贴了你的代码,它仍然是一样的。
    • @HunterTipton 您忘记将此答案标记为正确 :) 这对我们其他人来说很重要,因为我们不想浪费时间阅读已经完全回答的问题。
    猜你喜欢
    • 2012-02-08
    • 2012-06-01
    • 2018-05-14
    • 1970-01-01
    • 2023-04-01
    • 1970-01-01
    • 2021-11-02
    相关资源
    最近更新 更多