数据结构--链表--单链表归并排序mergesort

思路:

1.将链表的中点找到,对其切分成2条

2.继续步骤1,切成4条,8条。。。,直至每段链表只有1个元素

3.归并操作,对两两链表进行合并排序,并返回回并后的链表的头结点,依次向上递归回去

C++代码实现

链表头文件链接:https://github.com/hitskyer/course/tree/master/dataAlgorithm/chenmingming/linkedList/homework

//归并排序
// Created by mingm on 2019/3/23.
//
#include <iostream>
#include <time.h>
#include <cstdlib>
#include "./homework/singleList.cpp"
using namespace std;

ListNode GetMidNode(ListNode s)   //快慢指针法,获取中间节点
{
    ListNode fast, slow;
    fast = s->pNext;//让快指针早点到达末位,慢指针指向中点或者(偶数个长度时)中点前一个位置
    slow = s;
    while(fast && fast->pNext)
     {
        fast = fast->pNext->pNext;
        slow = slow->pNext;
     }
    return slow;
}
ListNode mergeList(ListNode L, ListNode R)  //归并函数
{
    if(L == NULL)   //如果一边为空,则返回另一边的头结点
        return R;
    if(R == NULL)
        return L;
    ListNode tempL = L, tempR = R;  //把左右表头存储起来
    ListNode temp = new SNode, emptyHead = temp; //利用一个空表头哨兵temp
    while(tempL && tempR)       //左右链表均不为空的话,进行数据比较
    {
        if(tempL->data < tempR->data)
        {
            temp->pNext = tempL;
            temp = temp->pNext;
            tempL = tempL->pNext;
        }
        else
        {
            temp->pNext = tempR;
            temp = temp->pNext;
            tempR = tempR->pNext;
        }
    }
    if(tempL)                   //如果左边还有剩余的节点,把其接入链表末尾
        temp->pNext = tempL;
    if(tempR)                   //如果右边还有剩余的节点,把其接入链表末尾
        temp->pNext = tempR;
    temp = emptyHead->pNext;     //实际链表数据节点表头
    delete emptyHead;           //释放new出来的哨兵
    emptyHead = NULL;
    return temp;                //返回链表数据头结点
}
ListNode divList(ListNode Lhead)
{
    if(Lhead == NULL || Lhead->pNext == NULL)   //链表长度为0或者1,不用排序
        return Lhead;
    ListNode Mid = GetMidNode(Lhead);   //获取链表中间节点(如果长度为2,则Mid是第一个节点)
    ListNode Rhead = Mid->pNext;    //右边链表表头地址
    Mid->pNext = NULL;              //断开左右链表
    ListNode L = divList(Lhead);    //继续对左右两条链表进行划分
    ListNode R = divList(Rhead);
    return mergeList(L,R);          //返回merge后的链表的表头
}
ListNode mergeSort(ListNode head)   //归并排序入口,将头结点地址传入
{
    if(head == NULL || head->pNext == NULL) //链表长度为0或者1,不用排序
        return head;
    else
        divList(head);  //长度大于1,则对其进行划分将链表切片
}

int main()
{
    srand((unsigned)time(NULL));    //用时间随机数种子
    size_t len = 10;       //测试链表最大长度
    for(size_t j = 0; j < len; ++j)
    {
        SingleList intList;
        for(size_t i = 0; i < j; ++i)
        {
            intList.AddTail(rand()%100);    //添加随机数到链表
        }
        cout << "before merge sort: " << endl;
        intList.PrintList();    //排序前链表打印
        intList.SetHeadNode(mergeSort(intList.GetHeadNode()));  //把排序后的链表的头结点设置成链表的头结点
        cout << "after merge sort: " << endl;
        intList.PrintList();    //排序后链表打印
    }
    return 0;
}

Valgrind检查结果

数据结构--链表--单链表归并排序mergesort