1. 程式人生 > >數據結構與算法系列:鏈表

數據結構與算法系列:鏈表

end 尾到頭 ppr 倒數 length head adl turn tac

鏈表定義:

1 // 鏈表結點
2 struct ListNode
3 {
4     int          m_nValue;
5     ListNode*    m_pNext;
6 };

常見問題:

#include <iostream>
#include <stack>


// 輸入數據
int Read()
{
    int value;
    std::cin >> value;
    return value;
}


// 創建鏈表
ListNode* CreateList(int nLen)
{
    ListNode* pHead = NULL;
    ListNode
* pCurr = NULL; ListNode* pNext = NULL; for (int nIdx = 0; nIdx < nLen; ++nIdx) { pNext = new ListNode; pNext->m_nValue = Read(); pNext->m_pNext = NULL; if (NULL == pHead) { pHead = pNext; } else { pCurr
->m_pNext = pNext; } pCurr = pNext; } if (NULL == pCurr) { delete pCurr; pCurr = NULL; } if (NULL == pNext) { delete pNext; pNext = NULL; } return pHead; } // 計算鏈表長度 int GetListLength(ListNode* pHead) { unsigned
int nLength = 0; ListNode* pNode = pHead; while (NULL != pNode) { ++nLength; pNode = pNode->m_pNext; } return nLength; } // 向鏈表的末尾添加一個結點 // pHead 是一個指向指針的指針,由於要修改頭結點,必須采用指向指針的指針 void AddToTail(ListNode** pHead, int value) { ListNode* pNew = new ListNode; pNew->m_nValue = value; pNew->m_pNext = NULL; if (NULL == *pHead) { *pHead = pNew; } else { ListNode* pNode = *pHead; while (NULL != pNode->m_pNext) { pNode = pNode->m_pNext; } pNode->m_pNext = pNew; } } // 刪除頭結點 // pHead 是一個指向指針的指針,由於要修改頭結點,必須采用指向指針的指針 void RemoveHead(ListNode** pHead) { if (NULL != *pHead) { if (NULL == (*pHead)->m_pNext) { pHead = NULL; } else { ListNode* pNode = *pHead; *pHead = (*pHead)->m_pNext; } } } // 刪除指定結點 // pHead 是一個指向指針的指針,由於要修改頭結點,必須采用指向指針的指針 void RemoveNode(ListNode** pHead, int value) { if (NULL == pHead || NULL == *pHead) { return; } ListNode* pToBeDeleted = NULL; if (value == (*pHead)->m_nValue) { pToBeDeleted = *pHead; *pHead = (*pHead)->m_pNext; } else { ListNode* pNode = *pHead; while (NULL != pNode->m_pNext && value != pNode->m_pNext->m_nValue) { pNode = pNode->m_pNext; } if (NULL != pNode->m_pNext && value == pNode->m_pNext->m_nValue) { pToBeDeleted = pNode->m_pNext; pNode->m_pNext = pNode->m_pNext->m_pNext; } } if (NULL == pToBeDeleted) { delete pToBeDeleted; pToBeDeleted = NULL; } } // 在O(1)時間刪除鏈表結點 void DeleteNode(ListNode** pHead, ListNode* pToBeDeleted) { if (NULL == pHead || NULL == pToBeDeleted) { return; } // 要刪除的結點不是尾結點 if (NULL != pToBeDeleted->m_pNext) { ListNode* pNext = pToBeDeleted->m_pNext; pToBeDeleted->m_nValue = pNext->m_nValue; pToBeDeleted->m_pNext = pNext->m_pNext; delete pNext; pNext = NULL; } // 鏈表只有一個結點 else if (*pHead == pToBeDeleted) { delete pToBeDeleted; pToBeDeleted = NULL; *pHead = NULL; } // 鏈表有多個結點,要刪除的結點是尾結點 else { ListNode* pNode = *pHead; while (pNode->m_pNext != pToBeDeleted) { pNode = pNode->m_pNext; } pNode->m_pNext = NULL; delete pToBeDeleted; pToBeDeleted = NULL; } } // 從頭到尾打印鏈表 void PrintList(ListNode* pHead) { ListNode* pNode = pHead; while (NULL != pNode) { std::cout << pNode->m_nValue << "\t"; pNode = pNode->m_pNext; } std::cout << std::endl; } // 從尾到頭打印鏈表 // 1、用棧實現 // 2、遞歸實現 void PrintListReversingly_Iteratively(ListNode* pHead) { std::stack<ListNode*> nodes; ListNode* pNode = pHead; while (NULL != pNode) { nodes.push(pNode); pNode = pNode->m_pNext; } while (!nodes.empty()) { pNode = nodes.top(); std::cout << pNode->m_nValue << "\t"; nodes.pop(); } std::cout << std::endl; } void PrintListReversingly_Recursively(ListNode* pHead) { if (NULL != pHead) { if (NULL != pHead->m_pNext) { PrintListReversingly_Recursively(pHead->m_pNext); } } std::cout << pHead->m_nValue << "\t"; } // 鏈表中倒數第 k 個結點 // 用兩個指針 ListNode* FindKthToTail(ListNode* pHead, unsigned int k) { if (NULL == pHead || 0 == k) { return NULL; } ListNode* pAhead = pHead; ListNode* pBehind = NULL; for (int nIdx = 0; nIdx < (int)k - 1; ++nIdx) { if (NULL != pAhead->m_pNext) { pAhead = pAhead->m_pNext; } else { return NULL; } } pBehind = pHead; while (NULL != pAhead->m_pNext) { pAhead = pAhead->m_pNext; pBehind = pBehind->m_pNext; } return pBehind; } // 鏈表的中間結點 ListNode* FindMidNode(ListNode* pHead) { if (NULL == pHead) { return NULL; } ListNode* pAhead = pHead; ListNode* pBehind = pHead; while (NULL != pAhead->m_pNext && NULL != pAhead->m_pNext->m_pNext) { pAhead = pAhead->m_pNext->m_pNext; pBehind = pBehind->m_pNext; } return pBehind; } // 判斷單鏈表是否有環 bool IsLoop(ListNode* pHead) { bool bLoop = false; if (NULL == pHead) { return bLoop; } ListNode* pAhead = pHead; ListNode* pBehind = pHead; while (NULL != pAhead->m_pNext && NULL != pAhead->m_pNext->m_pNext && pAhead != pBehind) { pAhead = pAhead->m_pNext->m_pNext; pBehind = pBehind->m_pNext; } if (pAhead == pBehind) { bLoop = true; } return bLoop; } // 反轉鏈表 // 1、叠代實現 // 2、遞歸實現 ListNode* ReverseList(ListNode* pHead) { ListNode* pReversedHead = NULL; ListNode* pNode = pHead; ListNode* pPrev = NULL; while (NULL != pNode) { ListNode* pNext = pNode->m_pNext; if (NULL == pNext) { pReversedHead = pNode; } pNode->m_pNext = pPrev; pPrev = pNode; pNode = pNext; } return pReversedHead; } ListNode* ReverseList_Recursively(ListNode* pHead) { if (NULL == pHead || NULL == pHead->m_pNext) { return pHead; } ListNode* pNode = pHead; ListNode* pReversedHead = ReverseList_Recursively(pNode->m_pNext); pNode->m_pNext->m_pNext = pNode; pNode->m_pNext = NULL; return pReversedHead; } // 合並兩個有序鏈表 ListNode* MergeList(ListNode* pHead1, ListNode* pHead2) { if (NULL == pHead1) { return pHead2; } else if (NULL == pHead2) { return pHead1; } ListNode* pMergeHead = NULL; if (pHead1->m_nValue < pHead2->m_nValue) { pMergeHead = pHead1; pMergeHead->m_pNext = MergeList(pHead1->m_pNext, pHead2); } else { pMergeHead = pHead2; pMergeHead->m_pNext = MergeList(pHead1, pHead2->m_pNext); } return pMergeHead; } // 兩個鏈表的第一個公共結點 ListNode* FindFirstCommonNode(ListNode* pHead1, ListNode* pHead2) { int nLength1 = GetListLength(pHead1); int nLength2 = GetListLength(pHead2); int nLengthDif = nLength1 - nLength2; ListNode* pListHeadLong = pHead1; ListNode* pListHeadShort = pHead2; if (nLength1 < nLength2) { nLengthDif = nLength2 - nLength1; pListHeadLong = pHead2; pListHeadShort = pHead1; } for (int nIdx = 0; nIdx < nLengthDif; ++nIdx) { pListHeadLong = pListHeadLong->m_pNext; } while (NULL != pListHeadLong && NULL != pListHeadShort && pListHeadLong != pListHeadShort) { pListHeadLong = pListHeadLong->m_pNext; pListHeadShort = pListHeadShort->m_pNext; } // 得到第一個公共結點 ListNode* pFirstCommonNode = pListHeadLong; return pFirstCommonNode; }

數據結構與算法系列:鏈表