数据结构与算法系列:链表
Posted 朔方
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构与算法系列:链表相关的知识,希望对你有一定的参考价值。
链表定义:
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;
}
以上是关于数据结构与算法系列:链表的主要内容,如果未能解决你的问题,请参考以下文章