单链表的原地归并排序实现

转载:http://www.cnblogs.com/sgzxy/archive/2009/06/14/1502975.html


#include <stdlib.h>

template
<class T>
struct Node
{
    Node(T d)
    {
        data 
= d;
        next 
= NULL;
    }
    T data;
    Node 
*next;
};

template
<class  T>
Node
<T> * GetTailNode( Node<T> *startNode, int length )
    
//按长度找到尾节点
{
    
while(length-- && startNode->next != NULL)
    {
        startNode 
= startNode->next;
    }
    
return startNode;
}

template
<class T, class CmpFunc>
Node
<T> * Merge( Node<T> *&startNode, int currBlockLen, CmpFunc cmp )
    
//从startNode开始,按currBlockLen二分,进行归并操作
{
    
bool canMerge = true;
    Node
<int> *leftBlock = startNode, *rightBlock = startNode;

    
// 找到rightBlock的头节点
    for(int i = 0; i<currBlockLen; ++i)
    {
        rightBlock 
= rightBlock->next;
        
if(rightBlock == NULL)
        {
            canMerge 
= false;
            
break;
        }
    }

    
if(!canMerge)
        
return NULL;

    Node
<int> *currSortedNode;                //排序结果的当前节点
    Node<int> *currTailNode = NULL;        //排序结果的尾节点,用于最后将排序结果与下一段链表数据连接
    int leftCount = 0, rightCount = 0;

    
//初始化currSortedNode
    if( cmp(leftBlock->data, rightBlock->data) )
    {
        
++rightCount;
        currSortedNode 
= startNode = rightBlock;
        rightBlock 
= rightBlock ->next;
    }
    
else
    {
        
++leftCount;
        currSortedNode 
= leftBlock;
        leftBlock 
= leftBlock ->next;
    }

    
while(true)
    {
        
if(leftCount == currBlockLen || leftBlock == NULL )
            
//当leftBlock完成排序时,leftBlock尾节点即为currSortedNode
        {
            currSortedNode
->next = rightBlock;            //剩下的rightBlock无需再排序,直接加入结果链
            currTailNode = GetTailNode( currSortedNode, currBlockLen-rightCount );            //找到结果的尾节点
            break;
        }
        
else if(rightCount == currBlockLen || rightBlock == NULL )
            
//当右Block完成排序,此时右Block的尾节点即为currSortedNode
        {
            Node
<T> *tmpNode = currSortedNode->next;            //记下下一段链表的头节点

            currSortedNode
->next = leftBlock;
            currTailNode 
= GetTailNode( currSortedNode, currBlockLen-leftCount );
            currTailNode
->next = tmpNode;                    //将结果链表与下一段链表连起来
            break;
        }
        
else
            
//普通的归并操作
        {
            
if(cmp(leftBlock->data, rightBlock->data))
            {
                
++rightCount;
                currSortedNode
->next = rightBlock;
                rightBlock 
= rightBlock->next;
            }
            
else
            {
                
++leftCount;
                currSortedNode
->next = leftBlock;
                leftBlock 
= leftBlock->next;
            }
            currSortedNode 
= currSortedNode->next;
        }
    }
    
return currTailNode->next != NULL ? currTailNode : NULL;                //返回NULL意味着一轮归并的结束
}

template
<class T, class CmpFunc>
void MergeSort( Node<T>* &dataLink, CmpFunc cmp )
{
    
int currBlockLen = 1;
    Node
<T> *lastTailNode;
    
whiletrue )
    {
        lastTailNode 
= Merge( dataLink, currBlockLen, cmp );
        
if(lastTailNode != NULL)
        {
            
do 
            {
                lastTailNode 
= Merge( lastTailNode->next, currBlockLen, cmp );
            } 
            
while ( lastTailNode != NULL );
            currBlockLen 
*= 2;
        }
        
else
            
break;
    }

}


inline bool IntCmp( int &a, int &b )
{
    
return a>b;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值