单链表归并排序

    1、对于链表来说,由于其元素的访问只能是顺序访问,而快速排序是改进后的冒泡排序,需要随机存取数据,不合适。采用归并排序方式对链表元素进行访问;

   2、需要的步骤 

        1) 分割:将一段链表分成两部分

        2) 排序:将两端已经有序的链表合并

        3)分治递归:递归操作


 //将链表Plist分割,并把分割后的两段链表第一个元素节点通过二级指针带出。其中Plist为该链表第一个元素节点指针
void CLinkList::SplitList(CLinkNode * pList, CLinkNode **pBegNode1, CLinkNode **pBegNode2)
{
    if (pList == NULL)
    {
        return;
    }

    CLinkNode *pFastNode = NULL;
    CLinkNode *pSlowNode = pList;

    if (pSlowNode == NULL || pSlowNode->pNext == NULL)
    {
        *pBegNode1 = pSlowNode;
        *pBegNode2 = NULL;
        return;
        
    }
    

    pFastNode = pSlowNode->pNext;


    
    while (pFastNode != NULL)
    {
        
        pFastNode = pFastNode->pNext;
        if (pFastNode != NULL)
        {
            pFastNode = pFastNode->pNext;
            //只有当快指针满足向后移动的条件时,慢指针才跟着移动,否则会导致分割不均匀
            pSlowNode = pSlowNode->pNext;
        }
        //printf("pSlowNode[%d], pFastNode[%d]\n", pSlowNode->Elem, pFastNode->Elem);
        
    }

    *pBegNode1 = pList;
    *pBegNode2 = pSlowNode->pNext;

    //printf("pList[%d], pSlowNode[%d]\n", pList->Elem, pSlowNode->Elem);

    //从中间断开链表

    pSlowNode->pNext = NULL;

}


//对两段有序链表进行排序

//通过虚拟节点进行

CLinkNode * CLinkList::SortList(CLinkNode * pListA, CLinkNode * pListB)
{

    CLinkNode CTmpNode;
    CTmpNode.pNext = NULL;
    
    CLinkNode *pTmpNode = &CTmpNode;
    
    if (pListA == NULL)
    {
        return pListB;
    }
    else if (pListB == NULL)
    {
        
        return pListA;
    }


    while (pListA != NULL && pListB != NULL)
    {

        if (pListA->Elem <= pListB->Elem)
        {
            pTmpNode->pNext= pListA;
            pTmpNode = pTmpNode->pNext;
            pListA = pListA->pNext;
        }
        else
        {
            pTmpNode->pNext= pListB;
            pTmpNode = pTmpNode->pNext;
            pListB = pListB->pNext;
        }
        
    }
    
    if (pListA != NULL)
    {
        pTmpNode->pNext = pListA;
    }
    else if (pListB != NULL)
    {
        pTmpNode->pNext = pListB;
    }

    
    
    return CTmpNode.pNext;
}

//通过递归方式合并两个链表

CLinkNode * CLinkList::SortList1(CLinkNode * pListA, CLinkNode * pListB)
{
    CLinkNode* pResult = NULL;
    
    if (pListA == NULL)
    {
        return pListB;
    }
    else if (pListB == NULL)
    {
        return pListA;
    }

    //
    if (pListA->Elem <= pListB->Elem)
    {
        pResult = pListA;
        pResult->pNext = SortList1(pListA->pNext, pListB);
    }
    else
    {
        pResult = pListB;
        pResult->pNext = SortList1(pListA, pListB->pNext);
        
    }
    return pResult;

}

//分治递归

//参数为out参数

void CLinkList::MergeSList(CLinkNode ** pListNode)
{

    if (*pListNode == NULL || (*pListNode)->pNext ==  NULL)
    {
        return;
    }

    CLinkNode *pFrontNode = NULL;
    CLinkNode *pBackNode = NULL;
    //链表分割,因为不能随机访问
    SplitList(*pListNode , &pFrontNode, &pBackNode);
    
    
    //递归调用,递归到没有节点时退出
    MergeSList(&pFrontNode);
    MergeSList(&pBackNode);

    //两个链表排序
    *pListNode = SortList1(pFrontNode, pBackNode);
    
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值