移除两个双向链表中的重复元素,每个链表中的元素不重复

移除两个双向链表中的重复元素,每个链表中的元素不重复,请给出算法。

ans: 该问题比单向链表要更加复杂一些,必须考虑并更新前向节点的指向情况,具体编码中存在一些难度,加上链表调试相对不容易,因此难度系数略高。

主要思路为:

  • 为每个链表添加哨兵节点,哨兵节点方便操作,因为头节点可能为重复元素
  • 访问链表A的首元素,和链表B的元素依次做对比
    • 当对比相等时,
      • 移除B的当前元素,更新B的指向
      • 移除A的当前元素,更新A的指向
      • break B
    • 当对比不相等时,
      • 链表B指针依次后移,直到为空
  • 当链表B的指针指向为空时,更新链表A的指针指向,继续对比,直到链表A为空
  • 打印出链表元素,因为是双向链表,必须两个方向打印,方能确保正确。
  • 代码如下,main中运行testList即可
typedef struct Node { //双链节点 定义int data;struct Node *prev, *next;
} DList;void PrintList(DList *head) { // 打印链表,DList *cur = head;while(cur != NULL) { // 正向打印printf("%d ", cur->data);cur = cur->next;if(cur) {printf(" -> ");}}printf(" || ");cur = head;while(cur->next != NULL) { // 寻找尾巴节点cur = cur->next;}while(cur != NULL) { // 反向打印printf("%d", cur->data);cur = cur->prev;if(cur) {printf(" -> ");}}
}void delSameDataNodes(DList **pHead1, DList **pHead2) { // 因会修改head 节点指向,所以必须使用二级指针if(*pHead1 == NULL || *pHead2 == NULL) {return;}DList* dummy1 = (DList *) malloc(sizeof(DList));  // 哨兵节点DList* dummy2 = (DList *) malloc(sizeof(DList));dummy1->next = *pHead1;  // 哨兵节点添加到头节点前面dummy2->next = *pHead2;dummy1->prev = NULL;  // 哨兵节点初始化dummy2->prev = NULL;dummy1->data = 0;dummy2->data = 0;DList* pc1 = *pHead1; // 为每个链表定义前节点,当前节点,后续节点指针DList* pf1 = dummy1;DList* pn1 = pc1->next;DList* pc2 = *pHead2;DList* pf2 = dummy2;DList* pn2 = pc2->next;int dup = 0; // 是否重复指示标志位while(pc1 != NULL) { // 链表A开始循环,逐一元素访问pf2 = dummy2; // 每当链表A访问新元素时, 链表B的3个指针必须从链表头重新开始指向,因pHead2有可能被移除,因此只能用哨兵节点pc2 = pf2->next;pn2 = pc2->next;while(pc2 != NULL) {if(pc1->data != pc2->data) {  // 两个链表元素不等时,链表2继续向后检索,知道链表末端,注意更新3个指针pf2 = pc2;pc2 = pn2;pn2 = (pn2 == NULL)?NULL:pn2->next; // 如果pn2 为空时,不能对其赋值} else {  // 两个链表元素相等时 ,需要设置标志位,跳过当前节点 pc2dup = 1;  // 设置标志位if(pn2) { // 如果pn2 非空时,跳过当前节点,并更新指针,因跳出当前循环,所以此处pc2可以不用设置pf2->next = pn2;pn2->prev = pf2;} else {pf2->next = NULL;}break;}}if(dup == 1) {dup = 0;if(pn1) {pf1->next = pn1;pn1->prev = pf1;pc1 = pn1;  // 此处pc1 必须设置pn1 = pn1->next;} else {pf1->next = NULL;}} else {pf1=pc1;pc1=pn1;pn1 = (pn1 == NULL)?NULL:pn1->next;}}*pHead1 = dummy1->next;*pHead2 = dummy2->next;(*pHead1)->prev = NULL;(*pHead2)->prev = NULL;free(dummy1);dummy1 = NULL;free(dummy2);dummy2 = NULL;
}void add2Tail(DList **head, int data) {DList *node = (DList*) malloc(sizeof(DList));node->data = data;node->next = NULL;node->prev = NULL;if(*head == NULL) {*head = node;} else {DList *cur =*head;while(cur->next!=NULL) {cur = cur->next;}cur->next = node;node->prev = cur;}
}void testList(void){DList *head1 = NULL;DList *head2 = NULL;add2Tail(&head1, 1);add2Tail(&head1, 2);add2Tail(&head1, 3);add2Tail(&head1, 4);add2Tail(&head1, 8);add2Tail(&head1, 9);printf("original list 1: ");PrintList(head1);printf("\n");add2Tail(&head2, 1);add2Tail(&head2, 2);add2Tail(&head2, 4);add2Tail(&head2, 5);add2Tail(&head2, 6);add2Tail(&head2, 7);add2Tail(&head2, 9);printf("original list 2: ");PrintList(head2);printf("\n---------------\n");delSameDataNodes(&head1, &head2);printf("remove duplicate list1: ");PrintList(head1);printf("\n");printf("remove duplicate list2: ");PrintList(head2);printf("\n");
}

结果显示如图:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/335885.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Springboot药物不良反应智能监测系统源码

一、系统简介 ADR指的是药品不良反应,即在合格药品在正常用法用量下,出现与用药目的无关或意外的有害反应。ADR数据辨别引擎、药品ADR信号主动监测引擎、ADR处置行为分析引擎。ADR数据辨别引擎,通过主动监测患者具象临床指标,比如…

【C#】C#实现PDF合并

文章目录 一、下载iTextSharp.dll下载iTextSharp.dll命名空间引入 二、界面设计三、代码全局变量选择文件夹的按钮确认合并的按钮 四、导出结果五、完整源码 一、下载iTextSharp.dll 下载iTextSharp.dll 可使用联机方式或者文件下载方式。 命名空间引入 代码开始时引入了一…

RK3568平台开发系列讲解(Linux系统篇)/dev/mem 物理内存映射到用户态

🚀返回专栏总目录 文章目录 一、/dev/mem 配置二、/dev/mem 设备的使用方法三、mmap 函数沉淀、分享、成长,让自己和他人都能有所收获!😄 一、/dev/mem 配置 /dev/mem 是 Linux 系统中的一个虚拟设备,通常与 mmap 结合使用,可以将设备的物理内存映射到用户态,以实现用…

[Docker] Mac M1系列芯片上完美运行Docker

docker pull qinchz/dm8-arm64 container_name: dm8ports:- "5236:5236"mem_limit: 1gmemswap_limit: 1gvolumes:- /data/dm8:/home/dmdba/data 数据库实例参数已修改,接近oracle使用习惯 #字符集 utf-8 CHARSET1 #VARCHAR 类型对象的长度以字符为单位 …

JDK21和 Flowable 7.0.0

JDK21和 Flowable 7.0.0 一.Flowable二.项目搭建1.依赖包2.数据库3.资源文件1.YML配置文件2.Drools kbase3.Drools rule4.DMN 决策表5.BPMN 流文件 4.BPMN 流程图绘制插件5.测试代码1.启动类2.Flowable 配置3.Camel 配置1.Camel 配置2.Camel Router 定义 4.扩展类监听1.外部工作…

WPS或word中英文字母自动调整大小写,取消自动首字母大写,全部英文单词首字母大小写变换方法

提示:写英文论文时,如何实现英文字母大小写的自动切换,不用再傻傻的一个字母一个字母的编辑了,一篇文章搞定WPS与Word中字母大小写切换 文章目录 一、WPS英文单词大小写自动修改与首字母大写调整英文字母全部由大写变成小写 或 小…

003集Class类应用实例—python基础入门实例

面向对象编程是一种编程方式,此编程方式的落地需要使用 “类” 和 “对象” 来实现,所以,面向对象编程其实就是对 “类” 和 “对象” 的使用。 类就是一个模板,模板里可以包含多个函数,函数里实现一些功能 对象则是根…

OpenFegin日志增强

OpenFeign配置日志增强功能 OpenFeign提供了日志打印功能,我们可以通过配置来调整日恙级别,从而了解Feign 中 Http请求的细节。 说白了就是对Feign接口的调用情况进行监控和输出 日志级别 NONE:默认的,不显示任何日志; BASIC&…

继承和多态的详解

文章目录 1. 继承1.1 继承的概念1.3 继承的语法1.3 父类成员访问1.3.1 子类中访问父类的成员变量1.3.2 子类中访问父类的成员方法 1.4 子类构造方法 2.super关键字2.1 super关键字的概念2.2 super和this的区别 3. 在继承中访问限定符的可见性4. 继承方式的分类5. 多态5.1 多态的…

ULINK2仿真器安装使用之工程设置

一、 ULINK2仿真器 ULINK2是ARM公司最新推出的配套RealView MDK使用的仿真器,是ULink仿真器的升级版本。ULINK2不仅具有ULINK仿真器的所有功能,还增加了串行调试(SWD)支持,返回时钟支持和实时代理等功能。开发工程师通…

Apache Doris (六十二): Spark Doris Connector - (2)-使用

🏡 个人主页:IT贫道-CSDN博客 🚩 私聊博主:私聊博主加WX好友,获取更多资料哦~ 🔔 博主个人B栈地址:豹哥教你学编程的个人空间-豹哥教你学编程个人主页-哔哩哔哩视频 目录 1. 将编译jar包加入本地Maven仓库

Ps:图层样式 - 混合选项

“图层样式”对话框中的“混合选项” Blending Options提供了多种方式来控制图层的可视化效果以及如何与其他图层交互。 常规混合 General Blending 混合模式 Blend Mode 设置当前图层的混合模式。 即,“图层”面板上的混合模式选项。 图层混合模式仅影响图层的原有…