題目:編寫代碼,以給定的x爲基準值將鏈表分割成兩部分,所有小於x的結點排在大於或等於x的結點之前。
解法一:交換結點法,回想學習快速排序的時候,也是以基準值將一組數劃分成兩部分,小於基準值的排在前面,大於基準值的排在後半部分。因此解決這個問題也可以使用兩個指針。如果鏈表頭結點開始遍歷,第一個需要移動的結點是第一個大於或等於基準值的結點,例如鏈表1->3->6->7->2->1->5,基準值設爲4,那麼第一個指針滑到6的時候應該停止,它需要被交換到後面,因爲6前面的結點值都是小於基準值的,所以和它交換的結點應該在它後面,需要找到一個小於基準值的結點交換到前面去,於是找到了結點2。交換結點6和2。然後兩個指針同時後移一位,在尋找需要交換的結點過程中指針一直滑到鏈表結尾時,表明鏈表中已經沒有需要交換的結點,這時候直接返回,循環結束。
void Partition(ListNode* pHead, int n)
{
if(pHead == NULL)
return;
ListNode *pCurr, *pNext;
pCurr = pHead;
while(pCurr->m_nValue < n)
{
pCurr = pCurr->m_pNext;
if(pCurr == NULL)
return;
}
pNext = pCurr;
while(pNext->m_nValue >= n)
{
pNext = pNext->m_pNext;
if(pNext == NULL)
return;
}
while(pCurr != NULL && pNext != NULL)
{
while(pCurr->m_nValue < n)
{
pCurr = pCurr->m_pNext;
if(pCurr == NULL)
return;
}
while(pNext->m_nValue >= n)
{
pNext = pNext->m_pNext;
//替換註釋部分
if(pNext == NULL)
return;
}
int tmp = pCurr->m_nValue;
pCurr->m_nValue = pNext->m_nValue;
pNext->m_nValue = tmp;
pCurr = pCurr->m_pNext;
pNext = pNext->m_pNext;
}
}
解法二:先分割再合併。創建兩個鏈表,before和after,before保存小於基準值的結點,after保存大於或等於基準值的結點,最後將兩個鏈表合併。
void Partition(ListNode** pHead, int n)
{
if(pHead == NULL)
return;
ListNode *beforeHead, *beforeEnd, *afterHead;
beforeHead = beforeEnd = afterHead = NULL;
ListNode* pNode = *pHead;
while(pNode != NULL)
{
ListNode* node = pNode->m_pNext;
if(pNode->m_nValue < n)
{
if(beforeHead == NULL)
{
beforeHead = pNode;
beforeEnd = pNode;
beforeEnd->m_pNext = NULL;
}
else
{
pNode->m_pNext = beforeHead;
beforeHead = pNode;
}
}
else
{
if(afterHead == NULL)
{
afterHead = pNode;
afterHead->m_pNext = NULL;
}
else
{
pNode->m_pNext = afterHead;
afterHead = pNode;
}
}
pNode = node;
}
if(beforeHead == NULL)
{
*pHead = afterHead;
return;
}
beforeEnd->m_pNext = afterHead;
*pHead = beforeHead;
}