从c中的链表数组返回排序列表

Posted

技术标签:

【中文标题】从c中的链表数组返回排序列表【英文标题】:Return a sorted list from an array of linked lists in c 【发布时间】:2021-08-12 19:26:06 【问题描述】:

我最后在这里要完成的是对一个包含多个链表的结构数组进行排序,并返回 1 个合并列表并进行排序。

例子

Input: [1->4->5, 1->3->4, 2->6] 
Output: 1->1->2->3->4->4->5->6 

输入是数组,如示例中所示,其中有 3 个不同的列表排序错误。

输出是最终的排序列表。

我试图做的是尝试像普通结构数组一样访问数组,然后一次排序 2 个。

我的代码

#include <stddef.h>


#ifndef STRUCT_LISTNODE
#define STRUCT_LISTNODE
typedef struct s_listnode

    int val;
    struct s_listnode* next;
 listnode;
#endif

#ifndef STRUCT_LISTNODE_ARRAY
#define STRUCT_LISTNODE_ARRAY
typedef struct s_listnode_array

    int size;
    listnode **array;
 listnode_array;
#endif


listnode* sort(listnode* first, listnode* second)
    listnode* newNode;
    if(first == NULL && second == NULL)
        return NULL;
    if (first == NULL)
        return second;
    if (second == NULL)
        return first;

// checking if the value on the first list bigger than the second or equal
    if (first->val >= second->val) \
   // if yes that means that the second should be first.
        newNode = second;
        newNode->next = sort(first, second->next);
     else 
        newNode = first;
        newNode->next = sort(first->next, second);
    
    return newNode;


listnode* merge_k_sorted_lists(listnode_array* head)

    listnode *newNode;
   for(int i = 0 ; i < head->size; i++)
       newNode = sort(head->array[0], head->array[i]);
   

   return newNode;

当我尝试运行我的代码时,我根本没有得到任何返回值。

【问题讨论】:

是时候学习如何使用 调试器 在监控变量及其值的同时逐语句执行代码。然后进入sort的递归调用。我还建议您在创建列表时同时使用笔和纸来“绘制”列表。在merge_k_sorted_lists 函数中,所有这些都应该让您更容易看到newNode 的变化以及它的变化。 你的函数sort真的在做merge merge_k_sorted_lists 中循环的第一次迭代将列表 0 用于sort 的两个参数。 【参考方案1】:

我做了一些更改,现在它似乎工作得更好,但有一个问题。

如果输入是一个具有 [[],[1]] 的数组并且预期的输出应该是 [1] 我没有得到返回并且我得到 SIGSEGV(信号 11)

#include <stddef.h>


#ifndef STRUCT_LISTNODE
#define STRUCT_LISTNODE
typedef struct s_listnode

    int val;
    struct s_listnode* next;
 listnode;
#endif

#ifndef STRUCT_LISTNODE_ARRAY
#define STRUCT_LISTNODE_ARRAY
typedef struct s_listnode_array

    int size;
    listnode **array;
 listnode_array;
#endif


listnode* sort(listnode* first, listnode* second)
     
    if(first == NULL && second == NULL)
        return NULL;
    if (first == NULL)
        return second;
    
    if (second == NULL)
        return first;

    
    listnode* newNode;
    
    if (first->val > second->val) 
        newNode = second;
        newNode->next = sort(first, second->next);
     else 
        newNode = first;
        newNode->next = sort(first->next, second);
    
    return newNode;



listnode* merge_k_sorted_lists(listnode_array* nodeArr)

    listnode *newNode;
    
    if(nodeArr->array[0]->next == NULL) 
        return nodeArr->array[0];
    if(nodeArr->size < 2)
        return nodeArr->array[0];

    for(int i = 1 ; i < nodeArr->size; i++)
        newNode = sort(nodeArr->array[0], nodeArr->array[i]);

   return newNode;

【讨论】:

【参考方案2】:

修复并简化了 merge_k_sorted_lists()。从 sort() 中删除了不需要的 if 语句。这与链表的自下而上合并排序中的第二个循环基本相同。递归的sort(),实际上是合并,对于大列表会导致栈溢出。

https://en.wikipedia.org/wiki/Merge_sort#Bottom-up_implementation_using_lists

#include <stdio.h>

#ifndef STRUCT_LISTNODE
#define STRUCT_LISTNODE
typedef struct s_listnode

    int val;
    struct s_listnode* next;
 listnode;
#endif

#ifndef STRUCT_LISTNODE_ARRAY
#define STRUCT_LISTNODE_ARRAY
typedef struct s_listnode_array

    int size;
    listnode **array;
 listnode_array;
#endif

listnode* sort(listnode* first, listnode* second)
listnode* newNode;
    if (first == NULL)
        return second;
    if (second == NULL)
        return first;
    if (first->val > second->val) 
        newNode = second;
        newNode->next = sort(first, second->next);
     else 
        newNode = first;
        newNode->next = sort(first->next, second);
    
    return newNode;


listnode* merge_k_sorted_lists(listnode_array* nodeArr)

listnode *newNode = NULL;
    for(int i = 0 ; i < nodeArr->size; i++)
        newNode = sort(newNode, nodeArr->array[i]);
    return newNode;


int main()

listnode list0[3] = 1, list0+1, 4,list0+2, 5,NULL;
listnode list1[3] = 1, list1+1, 3,list1+2, 4,NULL;
listnode list2[2] = 2, list2+1, 6,NULL;
listnode *lists[3] = list0, list1, list2;
listnode_array array[3] = 3, lists;
listnode *result, *tmp;
    result = merge_k_sorted_lists(array);
    for(tmp = result; tmp; tmp = tmp->next)
        printf("%1d ", tmp->val);
    printf("\n");
    return 0;


使用虚拟节点的非递归合并

listnode* sort(listnode* first, listnode* second)
listnode dMrg = 0, NULL;              /* dummy node */
listnode *pMrg = &dMrg;                 /* ptr to node in merged list */
    if (first == NULL)                  /* check for empty lists */
        return second;
    if (second == NULL)
        return first;
    while(1)                           /* merge the lists */
        if(first->val > second->val)
            pMrg = pMrg->next = second;
            second = second->next;
            if(second == NULL)
                pMrg->next = first;
                break;
            
        else
            pMrg = pMrg->next = first;
            first = first->next;
            if(first == NULL)
                pMrg->next = second;
                break;
            
        
    
    return dMrg.next;                   /* return merged list */


使用指针的非递归合并

listnode* sort(listnode* first, listnode* second)
listnode *pMrg;                         /* merged list */
listnode **ppMrg = &pMrg;               /* ptr to ptr to node in merged list */
    if (first == NULL)                  /* check for empty lists */
        return second;
    if (second == NULL)
        return first;
    while(1)                           /* merge the lists */
        if(first->val > second->val)
            *ppMrg = second;
            ppMrg = &(second->next);
            second = *ppMrg;
            if(second == NULL)
                *ppMrg = first;
                break;
            
        else
            *ppMrg = first;
            ppMrg = &(first->next);
            first = *ppMrg;
            if(first == NULL)
                *ppMrg = second;
                break;
            
        
    
    return pMrg;

【讨论】:

以上是关于从c中的链表数组返回排序列表的主要内容,如果未能解决你的问题,请参考以下文章

过滤链表并返回新的链表 C

在C中排序链表[关闭]

在C中对链表进行排序[关闭]

这是对多个链接列表进行排序的有效方法吗?

从c中的链表中删除名称时出错

LeetCode刷题之合并排序链表