1. 链表定义。
#ifndef _LISTNODE_
#define _LISTNODE_
struct ListNode
{
int m_value;
ListNode * m_pNext;
};
#endif
2. 初始化链表。
void InitList(ListNode * L)
{
L = nullptr;
cout << "InitList Success! " << endl;
}
3. 创建链表。共三种方法。
// ------创建线性表 1: 头结点插入法,头结点不放数据------
ListNode * CreateListFromHead()
{
ListNode * pHead = new ListNode;
pHead->m_pNext = nullptr;
if (pHead == nullptr)
{
cout << "分配内存失败!" << endl;
return nullptr;
}
int input;
while (cin>>input && input != -1)
{
ListNode *pTmp = new ListNode;
pTmp->m_value = input;
pTmp->m_pNext = pHead->m_pNext; //将节点插入到表头,这是头插法
pHead->m_pNext = pTmp;
pTmp = nullptr;
}
//pTmp = nullptr;
return pHead;
}
// ------创建线性表 2: 尾插法,头结点不放数据------
ListNode * CreateListFromTail2()
{
ListNode * pHead = new ListNode;
if (pHead == nullptr)
{
cout << "分配内存失败!" << endl;
return nullptr;
}
pHead->m_pNext = nullptr;
ListNode *pTail = new ListNode;
pTail = pHead;
int input;
while (cin>>input && input != -1)
{
ListNode *pTmp = new ListNode;
pTmp->m_value = input;
pTail->m_pNext = pTmp; //尾插法
pTail = pTmp;
pTmp = nullptr;
}
pTail->m_pNext = nullptr;
return pHead;
}
// ------创建线性表 3: 尾插法,无头结点------
ListNode * CreateListFromTail()
{
/*ListNode * pHead = new ListNode;
if (pHead == nullptr)
{
cout << "分配内存失败!" << endl;
return nullptr;
}*/
ListNode *pHead = nullptr;
ListNode *pTail = pHead;
int input;
while (cin>>input && input != -1)
{
ListNode *pTmp = new ListNode;
pTmp->m_value = input;
if (pHead == nullptr)
pHead = pTmp;
else
pTail->m_pNext = pTmp; //尾插法
pTail = pTmp;
pTmp = nullptr;
}
if (pTail != nullptr)
pTail->m_pNext = nullptr;
return pHead;
}
4. 插入。共两种方法。
// -------------------在pos位置的前方插入-----------------------------
void InsertListNodeFromFront(ListNode *&L, int pos, int value) //可能需要改变头结点,因此L要取&
{
ListNode *tmp = new ListNode;
tmp->m_value = value;
if (L == nullptr || pos == 0)
{
tmp->m_pNext = L;
L = tmp;
return;
}
if ( pos >= ListLen(L) || pos < 0)
{
cout << "Error input pos."<< endl;
return;
}
ListNode *pInsert = L;
while (--pos)
{
pInsert = pInsert->m_pNext;
}
tmp->m_pNext = pInsert->m_pNext;
pInsert->m_pNext = tmp;
return;
}
// -----------------在pos后插入--------------------
void InsertListNodeFromBack(ListNode *&L, int pos, int value)
{
ListNode *tmp = new ListNode;
tmp->m_value = value;
if (L == nullptr || pos == 0)
{
tmp->m_pNext = L;
L = tmp;
return;
}
if ( pos >= ListLen(L) || pos < 0)
{
cout << "Error input pos."<< endl;
return;
}
ListNode *pInsert = L;
while (pos--)
{
pInsert = pInsert->m_pNext;
}
tmp->m_pNext = pInsert->m_pNext;
pInsert->m_pNext = tmp;
return;
}
5. 删除。
void DeleteListNode(ListNode *&L, int value)
{
if (L == nullptr)
{
cout << "Error input L.";
return;
}
ListNode *pDelete = L;
if (L->m_value == value)
{
L = L->m_pNext;
delete pDelete;
return;
}
ListNode *pFront = nullptr;
while (pDelete != nullptr && pDelete->m_value != value)
{
pFront = pDelete;
pDelete = pDelete->m_pNext;
}
if (pDelete == nullptr)
{
cout << "Not found value in L.";
return;
}
if (pDelete->m_value == value)
{
pFront->m_pNext = pDelete->m_pNext;
delete pDelete;
}
return;
}
6. 翻转。
ListNode * ReverseList(ListNode *L)
{
if(L == nullptr || L->m_pNext == nullptr)
return nullptr;
ListNode * pCurrent = nullptr;
while (L != nullptr)
{
ListNode * tmp = L->m_pNext;
L->m_pNext = pCurrent;
pCurrent = L;
L = tmp;
}
/*DisplayList(L);
DisplayList(pCurrent);*/
return pCurrent;
}
7. 打印。
void DisplayList(ListNode * L)
{
ListNode * list = L;
while (list != nullptr)
{
cout << list->m_value << " -> ";
list = list->m_pNext;
}
cout << "null" << endl;
}
8. 链表长度。
int ListLen(ListNode *L)
{
int len = 0;
while (L != nullptr)
{
L = L->m_pNext;
++len;
}
return len;
}
9. 找到链表倒数第k个节点。
ListNode *FindKthNode(ListNode *L, int k)
{
if (ListLen(L) < k)
return nullptr;
ListNode *pFront = nullptr, *pBack = nullptr;
pFront = pBack = L;
int ii = 0;
while (ii++ < k-1)
{
pFront = pFront->m_pNext;
}
while (pFront->m_pNext != nullptr)
{
pFront = pFront->m_pNext;
pBack = pBack->m_pNext;
}
return pBack;
}
10. 合并两排序的链表。
ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
{
if (pHead1 == nullptr)
return pHead2;
if (pHead2 == nullptr)
return pHead1;
ListNode *pNewHead = nullptr, *pNewTail = nullptr;
ListNode *pNode1 = pHead1, *pNode2 = pHead2;
while (pNode1 != nullptr && pNode2 != nullptr)
{
ListNode *pTmp = nullptr;
if (pNode1->val < pNode2->val)
{
pTmp = pNode1;
pNode1 = pNode1->next;
}
else
{
pTmp = pNode2;
pNode2 = pNode2->next;
}
if (pNewHead == nullptr)
{
pNewHead = pNewTail = pTmp;
}
else
{
pNewTail->next = pTmp;
pNewTail = pNewTail->next;
}
}
if ( pNode1 == nullptr ) //和归并排序时的判断条件不一样。
{
pNewTail->next = pNode2;
}
if ( pNode2 == nullptr )
{
pNewTail->next = pNode1;
}
return pNewHead;
}
11. 删除链表中重复的节点. 180420
ListNode* deleteDuplication(ListNode* pHead)
{
if(pHead == nullptr)
return nullptr;
if (pHead->next == nullptr)
return pHead;
if (pHead->val == pHead->next->val && pHead->next->next == nullptr)
return nullptr;
ListNode *pNewNode = new ListNode(-1);
pNewNode->next = pHead;
ListNode *pLastNode = pNewNode;
ListNode *pCurNode = pHead;
ListNode *pNextNode = pHead->next;
int flag = 0;
while (pNextNode != nullptr)
{
while (pNextNode && pCurNode->val == pNextNode->val)
{
pNextNode = pNextNode->next;
pCurNode->next = pNextNode;
flag = 1;
}
if ( flag )
{
pCurNode = pNextNode;
pLastNode->next = pCurNode;
flag = 0;
if (pNextNode)
pNextNode = pNextNode->next;
}
if (pNextNode && pCurNode->val != pNextNode->val)
{
pLastNode = pLastNode->next;
pCurNode = pCurNode->next;
pNextNode = pNextNode->next;
}
}
return pNewNode->next;
}
12. 找两个链表第一个公共节点。 180424
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};
ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2)
{
if (pHead1 == nullptr || pHead2 == nullptr)
return nullptr;
ListNode *pNode1 = pHead1, *pNode2 = pHead2;
int cnt1 = 0, cnt2 = 0;
while (pNode1)
{
cnt1++;
pNode1 = pNode1->next;
}
while (pNode2)
{
cnt2++;
pNode2 = pNode2->next;
}
pNode1 = (cnt1>cnt2) ? pHead1 : pHead2;
pNode2 = (cnt1>cnt2) ? pHead2 : pHead1;
for (int ii=0; ii!=abs(cnt1-cnt2); ++ii)
pNode1 = pNode1->next;
ListNode * pRet = nullptr;
while (pNode1 && pNode2)
{
if (pNode1 == pNode2)
{
pRet = pNode1;
break;
}
else
{
pNode1 = pNode1->next;
pNode2 = pNode2->next;
}
}
return pRet;
}
13. 复杂链表的复制。180424
struct RandomListNode {
int label;
struct RandomListNode *next, *random;
RandomListNode(int x) :
label(x), next(NULL), random(NULL) {
}
};
// ---------------牛客网大神通过的版本---------------
RandomListNode* Clone(RandomListNode* pHead )
{
if(!pHead)
return NULL;
RandomListNode *currNode = pHead;
while(currNode)
{
RandomListNode *node = new RandomListNode(currNode->label);
node->next = currNode->next;
currNode->next = node;
currNode = node->next;
}
currNode = pHead;
while(currNode)
{
RandomListNode *node = currNode->next;
if (currNode->random)
node->random = currNode->random->next;
currNode = node->next;
}
//拆分
RandomListNode *pCloneHead = pHead->next;
RandomListNode *tmp;
currNode = pHead;
while(currNode->next)
{
tmp = currNode->next;
currNode->next =tmp->next;
currNode = tmp;
}
return pCloneHead;
}
// ------------ 自己的版本,未通过,错误尚未找出-------------
RandomListNode* Clone(RandomListNode* pHead)
{
if (pHead == nullptr)
return nullptr;
// ------------ 拷贝----------------
RandomListNode *pNode = pHead;
while (pNode)
{
RandomListNode *pTmp = new RandomListNode(*pNode);
pTmp->next = pNode->next;
pNode->next = pTmp;
if (pNode->random)
pTmp->random = pNode->random->next;
pNode = pTmp->next;
pTmp = nullptr;
}
// ------------- 拆分-----------------
pNode = pHead;
RandomListNode *pNewHead = pHead->next;
RandomListNode *pProcNode = pNewHead;
if (pNode) // 要让pNode走在pProcNode的前面。
{
pNode->next = pProcNode->next;
pNode = pNode->next;
}
while (pProcNode && pNode)
{
pProcNode->next = pNode->next; // pNode后面不会是空,所以这样赋值可以确保pProcNode后面不会是空
pProcNode = pProcNode->next;
pNode->next = pProcNode->next;
pNode = pNode->next;
}
return pNewHead;
}
14. 寻找链表中环的入口节点。180425
ListNode* EntryNodeOfLoop(ListNode* pHead)
{
if(pHead == nullptr || pHead->next == nullptr)
return nullptr;
ListNode *pFast = pHead, *pLow = pHead;
// ----------- 获取环的大小------------
int cnt = 0;
pFast = pFast->next;
pFast = (pFast==nullptr) ? pFast : pFast->next;
pLow = pLow->next;
++cnt;
while (pFast != pLow && pFast)
{
pFast = pFast->next;
pFast = (pFast==nullptr) ? pFast : pFast->next;
pLow = pLow->next;
++cnt;
}
if (pFast == nullptr)
return nullptr;
// --------获取环的入口-----------
pFast = pLow = pHead;
ListNode *pRet = nullptr;
for (int ii=0; ii != cnt; ++ii)
pFast = pFast->next;
while (pFast != pLow)
{
pFast = pFast->next;
pLow = pLow->next;
}
pRet = pFast;
return pRet;
}
15. 主函数测试。
int main(int argc, char **argv)
{
ListNode * L = new ListNode;
InitList(L);
cout << "请输入链表节点,以-1结束:" << endl;
L = CreateListFromTail();
DisplayList(L);
int pos = 1, value = 10;
cout << "在指定位置 " << pos << " 前方插入节点:" << value << endl;
InsertListNodeFromFront(L, pos, value);
DisplayList(L);
pos = 2; value = 20;
cout << "在指定位置 " << pos << " 后方插入节点:" << value << endl;
InsertListNodeFromBack(L, pos, value);
DisplayList(L);
cout << "删除值为 " << value << " 的节点:" << endl;
DeleteListNode(L, value);
DisplayList(L);
cout << "翻转链表:" << endl;
ListNode *R = ReverseList(L);
DisplayList(R);
getchar();getchar();
return 0;
}
测试结果: