alg : 单向链表排序

采用的是冒泡排序 + 插入节点, 操作的是指针不是数据.

支持单向链表回环, 非回环.

支持单向链表升序,降序排列.


排序函数:

BOOL ListSort(PNODE * ppNodeHead, BOOL bSortBySmallToBig)
{
    BOOL    bListIsLoop         =   FALSE;  ///< 链表是否回环
    BOOL    bNeedFixListTail    =   FALSE;  ///< 是否需要修复链表尾部Next指针(当链表头被移动后)
    BOOL    bListNodeSwapOK     =   FALSE;  ///< 节点交换是否成功, 如果是相同节点, 不需要交换

    size_t  nElementsCnt    =   0;      ///< 链表元素个数
    PNODE   pNodeTail       =   NULL;   ///< 链表尾节点

    PNODE   pNodeCur        =   NULL;   ///< 当前节点
    PNODE   pNodeCurParent  =   NULL;   ///< pNodeCur节点的父节点

    PNODE   pNodeReplace        =   NULL;   ///< 需要交换的节点, 根据bSortBySmallToBig标志可能为最小值节点或最大值节点
    PNODE   pNodeReplaceParent  =   NULL;   ///< pNodeReplace节点的父节点

    PNODE   pNodeNext       =   NULL;   ///< 下一个节点
    PNODE   pNodeNextParent =   NULL;   ///< pNodeNext节点的父节点

    PNODE   pNodeHeadTmp    =   NULL;   ///< 临时链表头, 使原始链表有父节点, 为了防止节点size过大, 需要new出来

    _ASSERT(NULL != ppNodeHead);
    _ASSERT(NULL != *ppNodeHead);

    bListIsLoop = IsListLoop(ppNodeHead, &nElementsCnt, &pNodeTail);   ///< 不关心链表是否回环, 只需要链表元素个数
    if (nElementsCnt <= 1)
        return TRUE;    ///< 链表节点2个以上, 才需要排序

    /// 加入临时链表头, 使链表头指针有父节点
    ListNodeCreate(&pNodeHeadTmp);

    pNodeHeadTmp->pNext = *ppNodeHead;  ///< 链表头指针

    /// 每个节点都记录父节点和子节点, 用于节点插入法排序
    /// 排序, 小的节点在前
    pNodeCurParent = pNodeHeadTmp;
    for (pNodeCur = pNodeHeadTmp->pNext; ; pNodeCur = pNodeCur->pNext)
    {
        if ((NULL == pNodeCur) || (pNodeCur == pNodeTail))
            break;  ///< 放在for循环条件中不行?

        pNodeReplace = pNodeCur;
        pNodeNextParent = pNodeCur;
        for (pNodeNext = pNodeCur->pNext; ; pNodeNext = pNodeNext->pNext)
        {
            if ((NULL == pNodeNext) || (pNodeNext == pNodeHeadTmp->pNext))
                break; ///< 放在for循环条件中不行?

            if (bSortBySmallToBig ? (pNodeNext->data < pNodeReplace->data) : (pNodeNext->data > pNodeReplace->data))
            {
                pNodeReplace = pNodeNext;           ///< 找到了需要交换的节点
                pNodeReplaceParent = pNodeNextParent;   ///< 为了交换节点, 需要记录该节点的父节点
            }

            pNodeNextParent = pNodeNext;
        }

        bNeedFixListTail = bListIsLoop && (pNodeCur == pNodeHeadTmp->pNext);
        bListNodeSwapOK = ListNodeSwap(&pNodeCur, &pNodeCurParent, &pNodeReplace, &pNodeReplaceParent);
        if (bListNodeSwapOK && bNeedFixListTail)
        {
            /// 对于回环情况的链表尾部节点, 当被交换的节点涉及到首节点时, 链表尾部节点->pNext应重新设置成首节点
            bListIsLoop = IsListLoop(ppNodeHead, &nElementsCnt, &pNodeTail);   ///< 求链表尾部节点
            pNodeTail->pNext = pNodeHeadTmp->pNext;
        }

#ifdef DEBUG_SHOW_LIST
        if (bListNodeSwapOK)
            ListShow(&pNodeHeadTmp->pNext); ///< @todo 测试用, 每交换一次节点, 就打印一次
#endif

        pNodeCurParent = pNodeCur;  ///< 记录当前节点的父节点
    }

    /// 在替换链表节点过程中, 链表首节点已经变了
    /// pNodeHeadTmp->pNext 一直指向的是真正的链表头
    *ppNodeHead = pNodeHeadTmp->pNext;  ///< 设置真正的链表头

    /// 释放临时链表头
    ListNodeFree(&pNodeHeadTmp);

    return TRUE;
}

测试用例结果: 测试单链表回环, 非回环, 升序, 降序.4种情况的组合

>> main


nTryIndex = 1


TestListSort(LISTNODE_CNT, IS_LIST_LOOP_NOT, SORT_BY_SMALL_TO_BIG);
uSeed = 55778563, sort = small to big
ListSort Before
========================================
ShowList >>
========================================
Head[0x0017C6C8], Head.pNext[0x0017C710], Head.data[0x60eaffff]
Node[0x0017C710], Node.pNext[0x0017C758], Node.data[0x09d00000]
Node[0x0017C758], Node.pNext[0x0017C7A0], Node.data[0x3b860000]
Node[0x0017C7A0], Node.pNext[0x0017C7E8], Node.data[0x0cdf0000]
Node[0x0017C7E8], Node.pNext[0x0017C830], Node.data[0x6255ffff]
Node[0x0017C830], Node.pNext[0x00000000], Node.data[0x4e9effff]
ListSort After
========================================
ShowList >>
========================================
Head[0x0017C710], Head.pNext[0x0017C7A0], Head.data[0x09d00000]
Node[0x0017C7A0], Node.pNext[0x0017C758], Node.data[0x0cdf0000]
Node[0x0017C758], Node.pNext[0x0017C830], Node.data[0x3b860000]
Node[0x0017C830], Node.pNext[0x0017C6C8], Node.data[0x4e9effff]
Node[0x0017C6C8], Node.pNext[0x0017C7E8], Node.data[0x60eaffff]
Node[0x0017C7E8], Node.pNext[0x00000000], Node.data[0x6255ffff]


TestListSort(LISTNODE_CNT, IS_LIST_LOOP_NOT, SORT_BY_BIG_TO_SMALL);
uSeed = 55778564, sort = big to small
ListSort Before
========================================
ShowList >>
========================================
Head[0x0017C6C8], Head.pNext[0x0017C710], Head.data[0x60edffff]
Node[0x0017C710], Node.pNext[0x0017C758], Node.data[0x33cd0000]
Node[0x0017C758], Node.pNext[0x0017C7A0], Node.data[0x014e0000]
Node[0x0017C7A0], Node.pNext[0x0017C7E8], Node.data[0x6addffff]
Node[0x0017C7E8], Node.pNext[0x0017C830], Node.data[0x0aa10000]
Node[0x0017C830], Node.pNext[0x00000000], Node.data[0x5df4ffff]
ListSort After
========================================
ShowList >>
========================================
Head[0x0017C7A0], Head.pNext[0x0017C6C8], Head.data[0x6addffff]
Node[0x0017C6C8], Node.pNext[0x0017C830], Node.data[0x60edffff]
Node[0x0017C830], Node.pNext[0x0017C710], Node.data[0x5df4ffff]
Node[0x0017C710], Node.pNext[0x0017C7E8], Node.data[0x33cd0000]
Node[0x0017C7E8], Node.pNext[0x0017C758], Node.data[0x0aa10000]
Node[0x0017C758], Node.pNext[0x00000000], Node.data[0x014e0000]


TestListSort(LISTNODE_CNT, IS_LIST_LOOP, SORT_BY_SMALL_TO_BIG);
uSeed = 55778565, sort = small to big
ListSort Before
========================================
ShowList >>
========================================
Head[0x0017C6C8], Head.pNext[0x0017C710], Head.data[0x60f0ffff]
Node[0x0017C710], Node.pNext[0x0017C758], Node.data[0x5dc8ffff]
Node[0x0017C758], Node.pNext[0x0017C7A0], Node.data[0x4716ffff]
Node[0x0017C7A0], Node.pNext[0x0017C7E8], Node.data[0x48dcffff]
Node[0x0017C7E8], Node.pNext[0x0017C830], Node.data[0x32eb0000]
Node[0x0017C830], Node.pNext[0x0017C6C8], Node.data[0x6d4bffff]
ListSort After
========================================
ShowList >>
========================================
Head[0x0017C7E8], Head.pNext[0x0017C758], Head.data[0x32eb0000]
Node[0x0017C758], Node.pNext[0x0017C7A0], Node.data[0x4716ffff]
Node[0x0017C7A0], Node.pNext[0x0017C710], Node.data[0x48dcffff]
Node[0x0017C710], Node.pNext[0x0017C6C8], Node.data[0x5dc8ffff]
Node[0x0017C6C8], Node.pNext[0x0017C830], Node.data[0x60f0ffff]
Node[0x0017C830], Node.pNext[0x0017C7E8], Node.data[0x6d4bffff]


TestListSort(LISTNODE_CNT, IS_LIST_LOOP, SORT_BY_BIG_TO_SMALL);
uSeed = 55778566, sort = big to small
ListSort Before
========================================
ShowList >>
========================================
Head[0x0017C6C8], Head.pNext[0x0017C710], Head.data[0x60f3ffff]
Node[0x0017C710], Node.pNext[0x0017C758], Node.data[0x07c60000]
Node[0x0017C758], Node.pNext[0x0017C7A0], Node.data[0x0cdf0000]
Node[0x0017C7A0], Node.pNext[0x0017C7E8], Node.data[0x26dd0000]
Node[0x0017C7E8], Node.pNext[0x0017C830], Node.data[0x5b35ffff]
Node[0x0017C830], Node.pNext[0x0017C6C8], Node.data[0x7ca2ffff]
ListSort After
========================================
ShowList >>
========================================
Head[0x0017C830], Head.pNext[0x0017C6C8], Head.data[0x7ca2ffff]
Node[0x0017C6C8], Node.pNext[0x0017C7E8], Node.data[0x60f3ffff]
Node[0x0017C7E8], Node.pNext[0x0017C7A0], Node.data[0x5b35ffff]
Node[0x0017C7A0], Node.pNext[0x0017C758], Node.data[0x26dd0000]
Node[0x0017C758], Node.pNext[0x0017C710], Node.data[0x0cdf0000]
Node[0x0017C710], Node.pNext[0x0017C830], Node.data[0x07c60000]

press any key run next test case

测试程序:

// prjListSortApp.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "Function.h"

#define LISTNODE_CNT            6       ///< 单向链表节点数量
#define IS_LIST_LOOP            TRUE    ///< 单向链表是否回环, 是
#define IS_LIST_LOOP_NOT        FALSE   ///< 单向链表是否回环, 否
#define SORT_BY_SMALL_TO_BIG    TRUE    ///< 排序方式, 升序
#define SORT_BY_BIG_TO_SMALL    FALSE   ///< 排序方式, 降序
#define TEST_LIST_SORT_CNT      10      ///< 测试ListSort的次数

void TestListSort(size_t nListNodeCnt, BOOL bIsListLoop, BOOL bSortBySmallToBig);
int _tmain(int argc, _TCHAR* argv[])
{
    size_t  nTryIndex   =   0;
    size_t  nTryCnt     =   TEST_LIST_SORT_CNT;
    _tprintf(L">> main\r\n");

    do 
    {
        _tprintf(L"\r\n\r\nnTryIndex = %d\r\n", ++nTryIndex);

        _tprintf(L"\r\n\r\nTestListSort(LISTNODE_CNT, IS_LIST_LOOP_NOT, SORT_BY_SMALL_TO_BIG);\r\n");
        TestListSort(LISTNODE_CNT, IS_LIST_LOOP_NOT, SORT_BY_SMALL_TO_BIG);


        _tprintf(L"\r\n\r\nTestListSort(LISTNODE_CNT, IS_LIST_LOOP_NOT, SORT_BY_BIG_TO_SMALL);\r\n");
        TestListSort(LISTNODE_CNT, IS_LIST_LOOP_NOT, SORT_BY_BIG_TO_SMALL);

        _tprintf(L"\r\n\r\nTestListSort(LISTNODE_CNT, IS_LIST_LOOP, SORT_BY_SMALL_TO_BIG);\r\n");
        TestListSort(LISTNODE_CNT, IS_LIST_LOOP, SORT_BY_SMALL_TO_BIG);

        _tprintf(L"\r\n\r\nTestListSort(LISTNODE_CNT, IS_LIST_LOOP, SORT_BY_BIG_TO_SMALL);\r\n");
        TestListSort(LISTNODE_CNT, IS_LIST_LOOP, SORT_BY_BIG_TO_SMALL);

        _tprintf(L"\r\npress any key run next test case\r\n");
        getwchar();
    } while (nTryCnt-- > 0);

    _tprintf(L"<< main\r\n");
    getwchar();
	return 0;
}

void TestListSort(size_t nListNodeCnt, BOOL bIsListLoop, BOOL bSortBySmallToBig)
{
    PNODE           pNode       =   NULL;
    static ULONG    uSeed       =   0;  ///< 使每次的随机种子都不同

    uSeed = (0 == uSeed) ? GetTickCount() : ++uSeed;
    srand(uSeed);
    _tprintf(L"uSeed = %d, sort = %s\r\n", 
        uSeed, 
        bSortBySmallToBig ? L"small to big" : L"big to small");

    /// 建立链表(节点数量, 是否回环)
    ListCreate(&pNode, nListNodeCnt, bIsListLoop);
    _tprintf(L"ListSort Before\r\n");
    ListShow(&pNode);

    /// 单向链表排序
    ListSort(&pNode, bSortBySmallToBig);
    _tprintf(L"ListSort After\r\n");
    ListShow(&pNode);

    /// 释放链表
    ListRemove(&pNode);
}

工具函数实现文件:

/// @file           Function.h
/// @brief          功能的实现

#ifndef __FUNCTION_H__
#define __FUNCTION_H__

#include "stdafx.h"
#include <windows.h>
#include <crtdbg.h>
#include <time.h>

// #define DEBUG_SHOW_LIST ///< 打印中间调试过程的单向链表

// for warning C4996: 'ExAllocatePool': was declared deprecated
#pragma warning(disable:4996)

typedef struct _node
{
    int data;
    struct _node * pNext;
} NODE,*PNODE;

/// 外部接口
/// @fn         ListSort
/// @brief      链表排序
/// @param      PNODE * ppNodeHead, 单向链表头指针, 支持回环单向链表
/// @param      BOOL bSortBySmallToBig, TRUE, 从小到大排序; FALSE, 从大到小排序
BOOL ListSort(PNODE * ppNodeHead, BOOL bSortBySmallToBig);

/// 内部接口

/// @fn         ListNodeSwap
/// @brief      交换2个节点(节点本身, 父节点, 子节点)
/// @param      PNODE * ppNodeCur, 当前节点
/// @param      PNODE * ppNodeCurParent, 当前节点的父节点
/// @param      PNODE * ppNodeReplace, 要交换的节点
/// @param      PNODE * ppNodeReplaceParent, 要交换的节点的父节点
BOOL ListNodeSwap(PNODE * ppNodeCur, 
                  PNODE * ppNodeCurParent,
                  PNODE * ppNodeReplace, 
                  PNODE * ppNodeReplaceParent);

/// @fn         CreateList
/// @brief       建立一个单向链表
/// @param      PNODE * ppNode, 链表首节点指针, *ppNode 必须为空
/// @param      size_t nListSize, 链表的元素个数
/// @param      BOOL bIsListLoop, 是否创建单回环链表, 如果是, 该链表首尾相接
void ListCreate(PNODE * ppNode, size_t nListSize, BOOL bIsListLoop);

void ListNodeCreate(PNODE * ppNode);
void ListNodeFree(PNODE * ppNode);

void ListRemove(PNODE * ppNode);
void ListShow(PNODE * ppNode);

/// @fn         IsListLoop
/// @brief      链表是否回环
/// @param      IN PNODE * ppNodeHead, 单向链表头指针
/// @param      OUT size_t * pnElementsCnt, 单向链表的元素计数
/// @param      OUT PNODE * ppNodeTail, 单向链表尾指针
/// @return     BOOL
/// @retval     TRUE, 链表回环
/// @retval     FALSE, 不是回环链表
/// @note OUT size_t & nElementsCnt 编译不过 ?
BOOL IsListLoop(IN PNODE * ppNodeHead, OUT size_t * pnElementsCnt, OUT PNODE * ppNodeTail);

/// @fn         GenerateRand
/// @param      产生一个在uMin~ulMax之间的随机数
ULONG GenerateRand(ULONG ulMin, ULONG ulMax);

// #ifdef __cplusplus
// }
// #endif

#endif

/// @file           Function.c
/// @brief          功能的实现

#include "stdafx.h"
#include "Function.h"

ULONG GenerateRand(ULONG ulMin, ULONG ulMax)
{
    ULONG       ulMinReal   =   min(ulMax, ulMin);
    ULONG       ulMaxReal   =   max(ulMax, ulMin);

    return (ULONG)((double)rand() / (RAND_MAX + 1) * (ulMaxReal - ulMinReal) + ulMinReal);
}

void ListNodeCreate(PNODE * ppNode)
{
    _ASSERT(NULL != ppNode);

    *ppNode = (PNODE)new BYTE[sizeof(NODE)];
    _ASSERT(NULL != *ppNode);

    (*ppNode)->data = GenerateRand(1, MAXLONG); ///< 结点的数据是随机的
    (*ppNode)->pNext = NULL;
}

void ListNodeFree(PNODE * ppNode)
{
    if ((NULL != ppNode) && (NULL != *ppNode))
    {
        delete *ppNode;
        *ppNode = NULL;
    }
}

void ListCreate(PNODE * ppNode, size_t nListSize, BOOL bIsListLoop)
{
    PNODE   pNodeHead   =   NULL;
    PNODE   pNodeCur    =   NULL;
    size_t  nIndex      =   0;

    if ((NULL == ppNode) || (NULL != *ppNode) || (nListSize < 1))
        return;

    ListNodeCreate(&pNodeHead);
    *ppNode = pNodeHead;

    pNodeCur = pNodeHead;
    for (nIndex = 1; nIndex < nListSize; nIndex++)
    {
        ListNodeCreate(&pNodeCur->pNext);
        pNodeCur = pNodeCur->pNext;
    }

    if (bIsListLoop)
        pNodeCur->pNext = pNodeHead; ///< 形成单链表回环
}

void ListShow(PNODE * ppNode)
{
    PNODE   pNodeCur    =   NULL;
    PNODE   pNodeHead   =   NULL;

    _tprintf(L"========================================\r\n");
    _tprintf(L"ShowList >>\r\n");
    _tprintf(L"========================================\r\n");

    if ((NULL == ppNode) || (NULL == *ppNode))
    {
        _tprintf(L"ppNode is invalid\n");
        return;
    }

    pNodeHead = *ppNode;

    _tprintf(L"Head[0x%p], Head.pNext[0x%p], Head.data[0x%8.8x]\n", 
        pNodeHead, pNodeHead->pNext, pNodeHead->data);

    pNodeCur = pNodeHead->pNext;
    while ((NULL != pNodeCur) && (pNodeCur != pNodeHead))
    {
        _tprintf(L"Node[0x%p], Node.pNext[0x%p], Node.data[0x%8.8x]\n",
            pNodeCur, pNodeCur->pNext, pNodeCur->data);
        pNodeCur = pNodeCur->pNext;
    }
}

void ListRemove(PNODE * ppNode)
{
    PNODE   pNodeHead   =   NULL;
    PNODE   pNodeCur    =   NULL;
    PNODE   pNodeNext   =   NULL;

    if ((NULL == ppNode) || (NULL == *ppNode))
    {
        return;
    }

    pNodeHead = *ppNode;

    /// 释放头节点之外的数据
    pNodeCur = pNodeHead->pNext;
    while ((NULL != pNodeCur) && (pNodeCur != pNodeHead))
    {
        pNodeNext = pNodeCur->pNext;
        ListNodeFree(&pNodeCur);
        pNodeCur = pNodeNext;
    }

    /// 释放头节点
    ListNodeFree(&pNodeHead);
    *ppNode = NULL;
}

BOOL IsListLoop(IN PNODE * ppNodeHead, OUT size_t * pnElementsCnt, OUT PNODE * ppNodeTail)
{
    BOOL bFind       =   FALSE;
    PNODE   pNodeCur    =   NULL;
    PNODE   pNodeHead   =   NULL;

    _ASSERT(NULL != ppNodeHead);
    _ASSERT(NULL != *ppNodeHead);
    _ASSERT(NULL != pnElementsCnt);
    _ASSERT(NULL != ppNodeTail);

    pNodeHead = *ppNodeHead;
    pNodeCur = pNodeHead->pNext;

    *ppNodeTail = pNodeCur;
    (*pnElementsCnt)++;

    while (NULL != pNodeCur)
    {
        if (pNodeCur == pNodeHead)
        {
            bFind = TRUE;
            break;
        }

        *ppNodeTail = pNodeCur;
        pNodeCur = pNodeCur->pNext;
        (*pnElementsCnt)++;
    }

    return bFind;
}

BOOL ListSort(PNODE * ppNodeHead, BOOL bSortBySmallToBig)
{
    BOOL    bListIsLoop         =   FALSE;  ///< 链表是否回环
    BOOL    bNeedFixListTail    =   FALSE;  ///< 是否需要修复链表尾部Next指针(当链表头被移动后)
    BOOL    bListNodeSwapOK     =   FALSE;  ///< 节点交换是否成功, 如果是相同节点, 不需要交换

    size_t  nElementsCnt    =   0;      ///< 链表元素个数
    PNODE   pNodeTail       =   NULL;   ///< 链表尾节点

    PNODE   pNodeCur        =   NULL;   ///< 当前节点
    PNODE   pNodeCurParent  =   NULL;   ///< pNodeCur节点的父节点

    PNODE   pNodeReplace        =   NULL;   ///< 需要交换的节点, 根据bSortBySmallToBig标志可能为最小值节点或最大值节点
    PNODE   pNodeReplaceParent  =   NULL;   ///< pNodeReplace节点的父节点

    PNODE   pNodeNext       =   NULL;   ///< 下一个节点
    PNODE   pNodeNextParent =   NULL;   ///< pNodeNext节点的父节点

    PNODE   pNodeHeadTmp    =   NULL;   ///< 临时链表头, 使原始链表有父节点, 为了防止节点size过大, 需要new出来

    _ASSERT(NULL != ppNodeHead);
    _ASSERT(NULL != *ppNodeHead);

    bListIsLoop = IsListLoop(ppNodeHead, &nElementsCnt, &pNodeTail);   ///< 不关心链表是否回环, 只需要链表元素个数
    if (nElementsCnt <= 1)
        return TRUE;    ///< 链表节点2个以上, 才需要排序

    /// 加入临时链表头, 使链表头指针有父节点
    ListNodeCreate(&pNodeHeadTmp);

    pNodeHeadTmp->pNext = *ppNodeHead;  ///< 链表头指针

    /// 每个节点都记录父节点和子节点, 用于节点插入法排序
    /// 排序, 小的节点在前
    pNodeCurParent = pNodeHeadTmp;
    for (pNodeCur = pNodeHeadTmp->pNext; ; pNodeCur = pNodeCur->pNext)
    {
        if ((NULL == pNodeCur) || (pNodeCur == pNodeTail))
            break;  ///< 放在for循环条件中不行?

        pNodeReplace = pNodeCur;
        pNodeNextParent = pNodeCur;
        for (pNodeNext = pNodeCur->pNext; ; pNodeNext = pNodeNext->pNext)
        {
            if ((NULL == pNodeNext) || (pNodeNext == pNodeHeadTmp->pNext))
                break; ///< 放在for循环条件中不行?

            if (bSortBySmallToBig ? (pNodeNext->data < pNodeReplace->data) : (pNodeNext->data > pNodeReplace->data))
            {
                pNodeReplace = pNodeNext;           ///< 找到了需要交换的节点
                pNodeReplaceParent = pNodeNextParent;   ///< 为了交换节点, 需要记录该节点的父节点
            }

            pNodeNextParent = pNodeNext;
        }

        bNeedFixListTail = bListIsLoop && (pNodeCur == pNodeHeadTmp->pNext);
        bListNodeSwapOK = ListNodeSwap(&pNodeCur, &pNodeCurParent, &pNodeReplace, &pNodeReplaceParent);
        if (bListNodeSwapOK && bNeedFixListTail)
        {
            /// 对于回环情况的链表尾部节点, 当被交换的节点涉及到首节点时, 链表尾部节点->pNext应重新设置成首节点
            bListIsLoop = IsListLoop(ppNodeHead, &nElementsCnt, &pNodeTail);   ///< 求链表尾部节点
            pNodeTail->pNext = pNodeHeadTmp->pNext;
        }

#ifdef DEBUG_SHOW_LIST
        if (bListNodeSwapOK)
            ListShow(&pNodeHeadTmp->pNext); ///< @todo 测试用, 每交换一次节点, 就打印一次
#endif

        pNodeCurParent = pNodeCur;  ///< 记录当前节点的父节点
    }

    /// 在替换链表节点过程中, 链表首节点已经变了
    /// pNodeHeadTmp->pNext 一直指向的是真正的链表头
    *ppNodeHead = pNodeHeadTmp->pNext;  ///< 设置真正的链表头

    /// 释放临时链表头
    ListNodeFree(&pNodeHeadTmp);

    return TRUE;
}

BOOL ListNodeSwap(PNODE * ppNodeCur, 
                  PNODE * ppNodeCurParent,
                  PNODE * ppNodeReplace, 
                  PNODE * ppNodeReplaceParent)
{
    _ASSERT(NULL != ppNodeCur);
    _ASSERT(NULL != ppNodeCurParent);

    _ASSERT(NULL != ppNodeReplace);
    _ASSERT(NULL != ppNodeReplaceParent);

    PNODE   pNodeCur            =   *ppNodeCur;
    PNODE   pNodeCurParent      =   *ppNodeCurParent;       ///< 当前节点的父节点

    PNODE   pNodeReplace        =   *ppNodeReplace;
    PNODE   pNodeReplaceParent  =   *ppNodeReplaceParent;   ///< pNodeReplace节点的父节点

    PNODE   pNodeTmp        =   NULL;   ///< 临时节点指针, 用于交换节点指针

    if (pNodeReplace != pNodeCur)
    {
        /// 用插入法交换pNodeCur和pNodeReplace(节点本身指针, 父节点,子节点)

        /// 将pNodeReplace放到pNodeCur原来的位置
        pNodeCurParent->pNext = pNodeReplace;

        pNodeTmp = pNodeReplace->pNext;

        if (pNodeCur->pNext != pNodeReplace)
        {
            /// 如果两个节点不相邻, 交换后, 最小值节点的下一个节点是是pNodeCur的下一个节点
            pNodeReplace->pNext = pNodeCur->pNext;
        }
        else
        {
            /// 这种情况下, pNodeCur的下一个节点是pNodeReplace
            /// 交换后, pNodeReplace->pNext 应该直接指向 pNodeCur
            pNodeReplace->pNext = pNodeCur;
        }

        /// 将pNodeCur放到pNodeReplace原来的位置
        pNodeReplaceParent->pNext = pNodeCur;
        pNodeCur->pNext = pNodeTmp;

        /// 使交换后的pNodeCur为pNodeReplace, 保证可以继续查找值
        /// 否则: 数据在链表尾部, 导致交换节点后, 不能再继续查找值
        *ppNodeCur = pNodeReplace;  ///< ! pNodeReplaceParent->pNext 指的的原来的 pNodeReplace 节点

        return TRUE;
    }
    else
        return FALSE;
}



你可能感兴趣的:(alg : 单向链表排序)