码迷,mamicode.com
首页 > 编程语言 > 详细

单链表归并排序

时间:2016-05-07 11:22:06      阅读:224      评论:0      收藏:0      [点我收藏+]

标签:

    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);
    
}

单链表归并排序

标签:

原文地址:http://blog.csdn.net/zhutianshidao1/article/details/51331682

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!