删除无序单链表中的值域重复的结点

题目:
有一个带头结点的单链表head,其中可能出值域重复的结点,设计一个算法删除值域重复的结点。要求在主函数中调用设计的算法,给出结果。

思路:删除某个结点值的重复结点,只需要遍历单链表找到与之相同的结点删除即可。删除多个不同结点值的重复结点,可以按链表顺序一个一个调用删除函数即可。因此可以使用递归实现。

测试数据:
样例1:1、2、3、4、5、6、7、8、9、0
输出1:1、2、3、4、5、6、7、8、9、0
样例2:1、2、3、4、3、5、5、6、7、8
输出2:1、2、3、4、5、6、7、8
样例3:1、1、1、1、5、5、7、8、8、8
输出3:1、5、7、8

细节:
定位到重复结点s的前一个结点q,方便修改指针,进行建链操作:q->next=s->next;递归调用删除重载私有函数时,需要判断指针不为空,在此处犯过错。

#include<iostream>
using namespace std;
template<typename DataType>
struct Node
{DataType data;//数据域Node<DataType>*next;//指针域
};template<class DataType>
class LinkList
{public:LinkList();//建立只有头结点一个空链表LinkList(DataType a[], int n);//建立n个元素的单链表~LinkList();//析构函数void Delete();//删除操作void PrintList();//输出
private:Node<DataType>*head;void Delete(Node<DataType>*p);//递归删除
};template<class DataType>
LinkList<DataType>::LinkList()
{head = new Node<DataType>;//生成头结点head->next = nullptr;//判空条件
}template<class DataType>
LinkList<DataType>::LinkList(DataType a[], int n)//头插法
{head = new Node<DataType>;//生成头结点head->next = nullptr;//判空条件for (int i = 0; i < n; i++){Node<DataType>*s=nullptr;s = new Node<DataType>;s->data = a[n - i - 1];s->next = head->next;head->next = s;}
}template<class DataType>
LinkList<DataType>::~LinkList()
{while (head){Node<DataType>*p = head;head= head->next;delete p;}
}template<class DataType>
void LinkList<DataType>::Delete()
{Delete(head->next);
}
template<class DataType>
void LinkList<DataType>::Delete(Node<DataType>*p)
{Node<DataType>*q = p;while (q&&q->next)//遍历链表,查看是否有与p值域相同的结点{if (p->data == q->next->data)//有,删除s{Node<DataType>*s = q->next; //生成新结点s,指向重复结点q->next = s->next;//修改指针,此时q->next是s的下一个结点,下一轮继续判断delete s;}else//不同,判断下一个结点q = q->next;}if(p->next)//查找下一个不同的结点Delete(p->next);//递归,不能用空指针调用
}template<class DataType>
void LinkList<DataType>::PrintList()
{Node<DataType>*p = head->next;while (p){cout << p->data << " ";p = p->next;}cout << endl;
}
int main()
{int r[10] = { 1,2,3,4,3,5,5,6,7,8 };LinkList<int>L(r, 10);L.PrintList();L.Delete();L.PrintList();return 0;
}

以上是我的做法

今天我的书到了,粗略看了一下剑指offer的目录居然瞥到上面的类似题目。

以下为书上题目的做法
删除链表结点两种思路:剑指offer上面限制了时间复杂度为O(1)
1.要想删除结点i,可以从链表的头结点a开始顺序遍历,发现结点h的m_pNext指向要删除的结点i,于是我们可以把结点h的的m_pNext指向i的下一个结点,即结点j。指针调整后,我们就可以安全地删除结点i并保证链表没有断开,由于是顺序查找,时间复杂度为O(n)。——简言之就是我上面删除一个相同结点的部分。

是不是一定要定位到被删除结点的前一个结点呢?答案是否定的。我们可以很方便地得到要删除结点的下一个结点。如果我们把下一个结点的内容复制到要删除的结点上覆盖原有的内容,再把下一个结点删除,那是不是就相当于把当前需要删除的结点删除了?

2.基于上述想法:我们要删除结点i,先把i的下一个结点j复制到i,然后把i的指针指向结点j的下一个结点。此时在删除结点j,其效果刚好是把结点i删除了。

细节:如果链表中只有一个结点,而我们又要删除链表的头结点,那么,此时我们在删除结点之后,还需要把链表的头结点设置为nullptr。
书上代码:

void DeleteNode(ListNode** pListHead, ListNode* pToBeDeleted)
{if(!pListHead || !pToBeDeleted)return;// 要删除的结点不是尾结点if(pToBeDeleted->m_pNext != nullptr){ListNode* pNext = pToBeDeleted->m_pNext;pToBeDeleted->m_nValue = pNext->m_nValue;pToBeDeleted->m_pNext = pNext->m_pNext;delete pNext;pNext = nullptr;}// 链表只有一个结点,删除头结点(也是尾结点)else if(*pListHead == pToBeDeleted){delete pToBeDeleted;pToBeDeleted = nullptr;*pListHead = nullptr;}// 链表中有多个结点,删除尾结点else{ListNode* pNode = *pListHead;while(pNode->m_pNext != pToBeDeleted){pNode = pNode->m_pNext;            }pNode->m_pNext = nullptr;delete pToBeDeleted;pToBeDeleted = nullptr;}
}

额,我又翻了一页书,找到类似的另一题,上面打的有点多,不想删了,而且也是基础。

那么在排序的链表中删除重复结点呢?
刚看图,书上配图竟然有瑕疵,一个重复结点没有,额。。。七个结点画了5个
根据它的意思,图应该是这样
a:1->2->3->3->4->4->5
b:1->2->5
怎么感觉跟我的题目意思不大一样。。。

看看它的思路吧【我已经有点不想打了】
解决这个问题的第一步是确定删除函数的参数。当然,这个函数需要输出入待删除结点的头结点。头结点可能与后面的结点重复,也就是说头结点也可能被删除,因此删除函数应该声明为void deleteDuplication(ListNode**pHead),而不是void deleteDuplication(ListNode*pHead)。

接下来我们从头遍历整个链表。如果当前结点(代码中的pNode)的值与下一个结点的值相同,那么它们就是重复的结点,都可以被删除。为了保证删除之后的链表仍然是相连的,我们要把当前结点的前一个结点(代码中的pPreNode)和后面值比当前结点的值大的结点相连。我们要确保pPreNode始终与下一个没有重复的结点连接在一起。
书上代码:

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;}if(pPreNode == nullptr)*pHead = pNext;elsepPreNode->m_pNext = pNext;pNode = pNext;}}
}

欢迎批评指正!

算法设计 删除无序单链表中的值域重复的结点相关推荐

  1. 链表问题13——删除无序单链表中值重复出现的节点

    题目 给定一个无序单链表的头节点head,删除其中值重复出现的节点. 原链表 删除后 1->2->3->3->4->2->4->1 1->2->3 ...

  2. 删除无序单链表中值重复出现的节点

    题目: 给定一个无序单链表的头节点head,删除其中值重复出现的节点. 请按以下要求实现两种方法. 方法一.时间复杂度O(N) 方法二.空间复杂度O(1) 基本思路   方法一.利用哈希表,依次遍历每 ...

  3. 链表问题13——删除无序单链表中值重复出现的节点(方法二)

    题目 同上一篇题目,本篇介绍方法二类似于选择排序的过程,时间复杂度为O(),额外空间复杂度为O(1), 思路 按顺序遍历节点 先是记录当前节点,然后去查看后面是否还有重复,有的话删掉,直到遍历完 然后 ...

  4. 设计一个算法,删除一个单链表L中元素值最大的结点(假设最大值结点是唯一的)

    设计一个算法,删除一个单链表L中元素值最大的结点(假设最大值结点是唯一的). #include <stdio.h> #include<malloc.h> typedef str ...

  5. 删除单链表中倒是第K个结点

    [问题描述] 设有头结点单链表,删除单链表中倒数第k个结点. [输入形式] 第一行输入若干个整数建立带头结点的单链表(以输入字符作为结束). 第二行输入一个整数k,表示删除倒数第k个结点. [输出形式 ...

  6. 狸猫换太子--删除无头单链表中结点

    狸猫换太子–删除无头单链表中结点 @(算法学习) 学习自<编程之美>. 很有意思的一种做法. 给定一个没有头指针的单链表,一个指针指向次单链表中的一个中间结点,删除此结点. 分析:这种根本 ...

  7. 删除按升序排列的单链表中的所有重复元素

    删除单链表中的所有重复元素 题目 解决思路 代码 说明 题目 存在一个按升序排列的链表,给你这个链表的头节点 head ,请你删除链表中所有存在数字重复情况的节点,只保留原始链表中没有重复出现的数字. ...

  8. 删除带头结点单链表中倒数第k个结点

    [问题描述] 设有头结点单链表,删除单链表中倒数第k个结点. [输入形式] 第一行重复输入整数建立带头结点的单链表,输入字符结束. 第二行输入一个整数k,表示删除倒数第k个结点. [输出形式] 输出删 ...

  9. 剑指offer:在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。

    在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针. 例如,链表1->2->3->3->4->4->5 处理后为 1-& ...

最新文章

  1. C++字符串类型和数字之间的转换
  2. asp.net读取用户控件,自定义加载用户控件
  3. NSHashTable and NSMapTable
  4. 【蓝桥杯 - 练习】k倍区间(思维,数组)
  5. 高职计算机专业用什么软件,【计算机专业论文】高职计算机专业CAD软件教学思考(共4772字)...
  6. shell脚本判断上一个命令是否执行成功
  7. td自动换行:设置table布局固定,td根据设定宽度自动换行
  8. linux下安装gcc及设置多版本gcc多版本共存(如果enable静态库,会报错,不知道为什么,忽略静态库就没问题了)...
  9. 大一学科不挂科 速冲方法推荐(高数上+高数下+线代+大物)
  10. AdventureWorks范例数据库
  11. SQLiteSpy 打开SqLite数据库文件
  12. 【darknet源码解析-24】shortcut_layer.h 和 shortcut_layer.c 解析
  13. 本地连接-IP和DNS设置
  14. 业务指标基础分析(excel)--python实现
  15. 文本域默认会放大缩小,如何把文本域设置为禁止推拽状态,从而固定大小呢
  16. 李彦宏:没有妻子就没有百度
  17. 算法手撕代码11~15
  18. 微信小程序底层框架实现原理
  19. Selective Sparse Sampling for Fine-grained Image Recognition
  20. 在现代意义上的电子计算机还未出现,2013年青海政法干警笔试真题解析:言语分析(7)...

热门文章

  1. 腾讯云数据万象:智能+存储双驱动,数倍提升内容生产效能
  2. 2021-2027全球与中国面部脂肪注射市场现状及未来发展趋势
  3. 目前世界上最好的卫星地图查看站 Atlas:提供更好的地图
  4. 程序员必收藏的几个网站
  5. [转贴] 淡淡的忧...淡淡的愁
  6. 用py2exe打包Python3.x应用
  7. MATLAB 单纯形法算法
  8. Windows 8以后的Windows操作系统关闭Driver Verifier的方法(disable Driver Verifier)
  9. 锐捷BGP基础配置(邻居建立、路由重发布、路由聚合、认证)
  10. 3300W充电桩源码;车载电源源码/包括PCB源理图