📜  双向链表合并排序的C程序(1)

📅  最后修改于: 2023-12-03 14:50:32.396000             🧑  作者: Mango

双向链表合并排序的C程序

双向链表合并排序是一种常见的排序算法,其核心思想是将两个已排序的双向链表合并成一个排序好的双向链表。本文将介绍双向链表合并排序的实现过程和C代码。

双向链表数据结构

双向链表是一种数据结构,其特点是每个节点包含两个指针,一个指向前一个节点,一个指向后一个节点。这种数据结构在链表操作中非常常见,因为它提供了方便的反向遍历功能。

typedef struct node{
    int data;
    struct node* next;
    struct node* prev;
}Node;

上面的代码定义了一个双向链表节点结构体。

合并排序算法

双向链表合并排序算法分为三个部分:

  1. 分割函数:将原始链表分割成两个子链表。
  2. 合并函数:将两个已排序的子链表合并成一个有序链表。
  3. 排序函数:递归排序原始链表。
/* 分割链表,返回链表后半部分的开始节点 */
Node* split(Node* head) {
    Node* fast = head;
    Node* slow = head;
    /* 将fast指针定位到链表中点 */
    while (fast && fast->next) {
        fast = fast->next->next;
        slow = slow->next;
    }
    Node* temp = slow->next;
    slow->next = NULL;
    return temp;
}

/* 合并两个已排序的链表 */
Node* merge(Node* l1, Node* l2) {
    Node dummy;
    dummy.next = NULL;
    Node* tail = &dummy;
    while (l1 && l2) {
        if (l1->data < l2->data) {
            tail->next = l1;
            l1 = l1->next;
        } else {
            tail->next = l2;
            l2 = l2->next;
        }
        tail->next->prev = tail;
        tail = tail->next;
    }
    tail->next = l1 ? l1 : l2;
    tail->next->prev = tail;
    return dummy.next;
}

/* 递归排序 */
Node* sortList(Node* head) {
    if (!head || !head->next)
        return head;
    Node* l1 = head;
    Node* l2 = split(head);
    l1 = sortList(l1);
    l2 = sortList(l2);
    return merge(l1, l2);
}
完整代码
typedef struct node{
    int data;
    struct node* next;
    struct node* prev;
}Node;

/* 分割链表,返回链表后半部分的开始节点 */
Node* split(Node* head) {
    Node* fast = head;
    Node* slow = head;
    /* 将fast指针定位到链表中点 */
    while (fast && fast->next) {
        fast = fast->next->next;
        slow = slow->next;
    }
    Node* temp = slow->next;
    slow->next = NULL;
    return temp;
}

/* 合并两个已排序的链表 */
Node* merge(Node* l1, Node* l2) {
    Node dummy;
    dummy.next = NULL;
    Node* tail = &dummy;
    while (l1 && l2) {
        if (l1->data < l2->data) {
            tail->next = l1;
            l1 = l1->next;
        } else {
            tail->next = l2;
            l2 = l2->next;
        }
        tail->next->prev = tail;
        tail = tail->next;
    }
    tail->next = l1 ? l1 : l2;
    tail->next->prev = tail;
    return dummy.next;
}

/* 递归排序 */
Node* sortList(Node* head) {
    if (!head || !head->next)
        return head;
    Node* l1 = head;
    Node* l2 = split(head);
    l1 = sortList(l1);
    l2 = sortList(l2);
    return merge(l1, l2);
}

int main() {
    Node n1, n2, n3, n4, n5;
    n1.data = 3;
    n1.next = &n2;
    n1.prev = NULL;
    n2.data = 1;
    n2.next = &n3;
    n2.prev = &n1;
    n3.data = 4;
    n3.next = &n4;
    n3.prev = &n2;
    n4.data = 2;
    n4.next = &n5;
    n4.prev = &n3;
    n5.data = 5;
    n5.next = NULL;
    n5.prev = &n4;

    Node* head = &n1;
    head = sortList(head);

    while (head) {
        printf("%d ", head->data);
        head = head->next;
    }

    return 0;
}