采用的是冒泡排序 + 插入节点, 操作的是指针不是数据.
支持单向链表回环, 非回环.
支持单向链表升序,降序排列.
排序函数:
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; }
>> 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; }