如何在C

时间:2018-02-04 01:50:05

标签: c merge linked-list mergesort doubly-linked-list

我目前正在开发一个项目,该项目接收带有数据的两个文本文件,并将它们分成两个单独的链接列表。我的下一步是创建一个函数,该函数接收这两个列表,按ID递增顺序对它们进行合并和排序。我已经开始实现了但是我很困难,需要一些指导我对合并排序函数做错了什么。其他所有工作正常,例如单独排序每个列表。我只需要一种方法来接受这两个列表并在C中合并它们。注意:我使用的是Ubuntu gcc编译器。

struct List *merge_list(struct List *list1, struct List *list2)
{
    struct Node *hand1 = list1->head;
    struct Node *hand2 = list2->head;
    struct Node *tmp1, *tmp2 = NULL;
    struct List *list3 = malloc(sizeof(struct List));

    while(list1 && list2 != NULL)
    {
            if(ptr1->id > ptr2->id)
            {
                    ptr1 = list3->head;
                    ptr1 = ptr1->next;
            }
            else
            {
                    ptr2 = list3->head;
                    ptr2 = ptr2->next;
            }
    }
    return list3;
}

注意:这是我的节点和列表结构

struct Node {
  int id;
  char *fname;
  char *lname;
  char *department;
  float gpa;
  struct Node *next;
  struct Node *prev;
};

struct List {
  struct Node *head;
  struct Node *tail;
  int count;
};

2 个答案:

答案 0 :(得分:0)

合并两个排序列表:

while (hand1 && hand2) {
    if (hand1->id <= hand2->id) {
        tmp = hand1;
        hand1 = hand1->next;
    } else {
        tmp = hand2;
        hand2 = hand2->next;
    }

    insertNode(list3, tmp);
}

// either hand1 or hand2 will have some leftover elements
// they can be added to the back of list by inserting the head
if (hand1)
    insertNode(list3, hand1);
else
    insertNode(list3, hand2);

我已经给你写了insertNode()。为了保留两个列表的排序,它应该在列表的末尾插入节点。由于您正在跟踪列表的尾部,因此应该非常容易。

我会将list3中的指针初始化为NULL并将计数初始化为0,它应该使insertNode()更容易编写。

答案 1 :(得分:0)

您有两个双向链表并且两者都已排序,您的要求是创建一个函数,该函数接收这两个列表以按递增顺序按ID进行合并和排序。由于双向链表都已经排序,因此您不需要先将它们合并然后排序,但可以按排序顺序合并它们。

你可以这样做:

struct Node * merge_list(struct Node * head1, struct Node * head2)
{   
    struct Node* head3 = NULL;
    struct Node* p1 = head1;
    struct Node* p2 = head2;
    struct Node* p3 = NULL;

    while (p1 != NULL || p2 != NULL)
    {   
        struct Node * tmp = NULL;
        if (p1 == NULL) {
            tmp = p2;
            p2 = NULL;
        } else if (p2 == NULL) {
            tmp = p1;
            p1 = NULL;
        }

        if ((p1 != NULL) && (p2 != NULL)) {
            if (p1->id < p2->id) {
                tmp = p1;
                p1 = p1->next;
            } else {
                tmp = p2;
                p2 = p2->next;
            }
        }

        if (head3 == NULL) {
            head3 = tmp;
        } else {
            p3->next = tmp;
            tmp->prev = p3;
        }
        p3 = tmp;
    }
    return head3;
}

输出:

List 1:
1  3  7
List 2:
2  4  6  8 
Merged list:
1  2  3  4  6  7  8

关于merge_list()功能的几点:

  • 在这个merge_list()函数中,我将获取列表的head个指针,并返回合并列表的head指针。但我可以看到你struct List维护了列表的headtail指针。因此,您需要在函数中相应地进行更改,例如参数和返回类型将是struct List *类型,并且在函数中,您还需要处理合并列表tail指针。核心逻辑将是相同的。
  • 函数merge_list()修改两个列表,它们作为参数传递给它,因为它重置列表节点的nextprev指针以便合并它们。因此,在此函数调用之后,作为参数传递的列表都不再有效。将他们的headtail指针设置为NULL
  • 如果您希望在merge_list()调用之后将列表作为参数传递给merge_list(),则需要在添加到合并列表时复制节点。为此,您需要将内存分配给tmp以及将tmp设置为p1p2的位置,而是将值分配给tmp成员。在这里要小心,如果结构Node的成员是指向某个内存的指针,那么将内存分配给该tmp成员指针并复制该值。

希望这有帮助。