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

题目:
有一个带头结点的单链表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. 【maven插件】maven-resources-plugin
  2. python微信开发实例 pdf 百度网盘_用python看女神微信里的百度云资源有啥?
  3. MySql(18)——Linux MySQL主从配置
  4. linux安装pl sql,Linux上安装配置InstantClient及64位系统Pl/SQL配置
  5. 查找Python中给定字符串的所有排列
  6. dnt 删除不良数据
  7. 深度学习(四十五)条件对抗网络
  8. 朱海舟宣布新一批应用已经适配锤子TNT 网友:救救海舟
  9. C++面试题,平时面试不可缺少的!
  10. Codeforces Round #248 (Div. 2) B. Kuriyama Mirai's Stones
  11. 苹果cms用php几,苹果CMS用的B站播放器
  12. 学习笔记(1):2020软考数据库系统工程师-基础知识培训视频-计算机系统--体系结构概述...
  13. msicuu.exe,msizap.exe
  14. Weblogic控制台中文显示还是英文显示,浏览器语言设置决定的
  15. mysql被禁用了怎么办_数据库mysql存储遇到禁用怎么办?
  16. Transformers in Vision: A Survey论文翻译
  17. 香蕉为什么能做随机数生成器?因为,它是水果界的“辐射之王”
  18. 文件系统专栏 | 之文件系统架构
  19. C语言中的void*是什么?
  20. 法律工作者在用的小众但功能强悍的效率工具有这些

热门文章

  1. 分布式文件存储——FastDFS
  2. html聚光灯特效,CSS3聚光灯效果实现代码
  3. 中文树库-CTB短语结构标记
  4. 动态库(.so)的制作
  5. 关于“穿着棉袄洗澡”
  6. 下一代计算机机房,下一代数据中心
  7. Go语言适用于Web开发吗
  8. 《Kotlin 极简教程 》第5章 集合类(2)
  9. 什么是异步,以及实现原理
  10. 低成本2.4G无线收发器芯片