列表是一個圓形的列表,因此尾指針是不夠好,因爲在代碼如圖所示,tail->下將導致頭指針。該代碼沒有檢查只有單個節點的空列表或列表。
冒泡排序通常需要循環內的循環(外循環和內循環)。每個內部循環將應該是最後一個的節點移動到列表的末尾。第一個內部循環放置最後一個節點,第二個內部循環將下一個節點放置到最後一個節點,等等,最後一個內部循環將第二個節點放置到位。
爲了交換節點,代碼需要能夠更新先前節點的下一個指針。例如:
A->B->C->D // to swap B and C, A's next pointer needs to be updated
A->C->B->D // along with B and C's next pointers
由於返回的指針是尾指針,尾部指針既可以在第一內部循環後進行設置,因爲這是當最後節點被放置就位,或分選後,列表可以被掃描以找到最後一個節點。
我建議循環列表轉換爲正常列表中的排序函數內:由於節點
Node *head = ptr->next; // same as above
Node *tail = ptr; // same as above
tail->next = NULL; // convert to normal list
這簡化確定列表的末尾(檢查NULL與一個指針指向一個特定節點)在列表的開頭或結尾可能會在排序過程中交換。
可以通過跟蹤列表末尾的已排序節點來優化代碼,以避免掃描和比較已排序的節點。
優化氣泡排序的示例代碼。在設置pHead後,列表從圓形變爲正常(pTail-> next = NULL)。 pEnd用於跟蹤未排序列表的末尾並初始化爲NULL。 pnEnd基於亂序檢查跟蹤未排序列表的末尾,並用於爲下一個內部循環設置pEnd。排序是在pEnd是列表中的第二個節點時完成的,因爲第一個節點作爲單個節點也將被排序。 ppCurr是指向當前節點的指針的指針,並且是指向pHead或某個節點下一個指針的指針,它簡化了處理第一個和後面的節點的邏輯(在不支持指針的其他語言中,一個虛擬節點可以類似的方式使用,使用類似於* ppCurr的dummy.next)。內部循環首次完成的檢查將pTail設置爲最後一個節點,如果最後兩個節點已交換,則該節點可能已更改。排序完成後,將pTail-> next設置爲pHead將列表更改爲循環。
/* bubble sort circular linked list */
NODE * SortList(NODE *pTail)
{
NODE *pHead; /* ptr to first node */
NODE *pEnd; /* ptr to end of unsorted part of list */
NODE *pnEnd; /* pEnd for next pass */
NODE *pNext; /* ptr to next node */
NODE **ppCurr; /* ptr to ptr to curr node */
if(pTail == NULL || pTail->next == pTail) /* if empty list or single node */
return pTail; /* return pTail */
pHead = pTail->next;
pEnd = pTail->next = NULL; /* change to normal list */
do{
ppCurr = &pHead; /* set ppCurr to start of list */
pnEnd = pHead->next; /* set pnEnd to 2nd node */
while((pNext = (*ppCurr)->next) != pEnd){
if((*ppCurr)->data > pNext->data){ /* if out of order swap */
(*ppCurr)->next = pNext->next;
pnEnd = pNext->next = *ppCurr;
*ppCurr = pNext;
}
ppCurr = &(*ppCurr)->next; /* advance to next node */
}
if(pEnd == NULL) /* if first time, set pTail */
pTail = *ppCurr; /* in case last two nodes swapped */
pEnd = pnEnd; /* update pEnd since rest of list is sorted */
}while(pEnd != pHead->next); /* loop until pEnd => 2nd node */
pTail->next = pHead; /* change to circular list */
return pTail;
}
首先,感謝您的answer.I使用了兩個循環排序泡沫,但我無法解決環路的死循環,但你可以給我一個簡單的泡沫安排 – yggdrasil
@Lucir - 一個簡單的結束循環的方法是使用交換標誌。在外部循環中將swap標誌設置爲0,並且在內部循環中,如果節點出現故障並交換,則將swap標誌設置爲1.然後在外部循環中,如果swap == 0,則中斷(意味着所有節點都按順序),否則,如果交換標誌設置爲1,則執行另一個循環。 – rcgldr
非常感謝。這是一個很好的幫助。祝你有美好的一天。 – yggdrasil