题目:在一个排序的链表中,如何删除重复的结点?
思路:从头遍历整个链表,如果当前节点pNode的值与下一个节点的值相同,那么它们就是重复的节点,可以被删除。并将当前节点的前一个节点pPreNode始终与下一个没有重复的节点连接在一起。由于头结点pHead也可能与后面的节点重复,此时会改动头指针,因此必须把删除函数的pHead参数设为指向指针的指针,即ListNode** pHead,而不是void deleteDuplication(ListNode* pHead。
完整代码如下:
#include <iostream>
//#include <cstdio>
using namespace std;
struct ListNode{
int m_nValue;
ListNode* m_pNext;
};
void DeleteDuplication(ListNode** pHead){
if(pHead == nullptr || *pHead == nullptr)
return;
ListNode* pPreNode = nullptr;
ListNode* pNode = *pHead;
while(pNode != nullptr){
ListNode* pNext = pNode->m_pNext;
bool needDelete = false;
if(pNext != nullptr && pNext->m_nValue == pNode->m_nValue) //判断下一个节点的值是否与当前节点的值相同
needDelete = true;
if(!needDelete){ //如果不同,继续向后遍历
pPreNode = pNode;
pNode = pNode->m_pNext;
}
else{ //如果相同,则开始删除重复节点
int value = pNode->m_nValue;
ListNode* pToBeDel = pNode;
while(pToBeDel != nullptr && pToBeDel->m_nValue == value){
pNext = pToBeDel->m_pNext;
delete pToBeDel;
pToBeDel = nullptr;
pToBeDel = pNext; //返回while,继续判断
}
if(pPreNode == nullptr)
*pHead = pNext; //头结点与后面节点重复,已被删除。重新设置头结点
else
pPreNode->m_pNext = pNext;
pNode = pNext; //返回while,继续判断
}
}
}
ListNode* CreateListNode(int value)
{
ListNode* pNode = new ListNode(); //初始化操作
pNode->m_nValue = value;
pNode->m_pNext = nullptr;
return pNode;
}
void ConnectListNodes(ListNode* pCurrent, ListNode* pNext)
{
pCurrent->m_pNext = pNext;
pNext->m_pNext = nullptr;
}
int main(){
ListNode* pNode1 = CreateListNode(1); //在CreateListNode()中对节点pnode1必须进行初始化操作,下同
ListNode* pNode2 = CreateListNode(2);
ListNode* pNode3 = CreateListNode(3);
ListNode* pNode4 = CreateListNode(3);
ListNode* pNode5 = CreateListNode(4);
ListNode* pNode6 = CreateListNode(4);
ListNode* pNode7 = CreateListNode(5);
ConnectListNodes(pNode1, pNode2);
ConnectListNodes(pNode2, pNode3);
ConnectListNodes(pNode3, pNode4);
ConnectListNodes(pNode4, pNode5);
ConnectListNodes(pNode5, pNode6);
ConnectListNodes(pNode6, pNode7);
ListNode* pHead = pNode1;
DeleteDuplication(&pHead);
ListNode* pNode = pHead;
while(pNode != nullptr){
cout << pNode->m_nValue << endl; //打印一遍链表,验证是否删除了重复的节点
pNode = pNode->m_pNext;
}
return 0;
}