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

news2025/1/19 2:30:15

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

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 {  // 两个链表元素相等时 ,需要设置标志位,跳过当前节点 pc2
                dup = 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.coloradmin.cn/o/1370387.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Qt之有趣的数字钟

一.效果 基于网络代码修改,支持时、分、秒;支持滑动、翻页和旋转。 二.实现 #include <QtCore> #include <QPainter> #include <QAction> #include <QWidget> #include <QMainWindow> #include <QTimer> #include <QKeyEvent> #…

React ant table警告:Each child in a list should have a unique “key“ prop.

如下图&#xff1a; 原因 React Ant table表格每一行都需要一个唯一标识来确保不重复&#xff0c;如果不加该属性&#xff0c;就会出现这个警告。 修复 添加这一行&#xff1a; rowKey{(record) > record.id} # id为行idTable代码段&#xff1a; <TabledataSourc…

Armv8-R AArch32 architecture概念学习

提示 该博客主要为个人学习&#xff0c;通过阅读官网手册整理而来&#xff08;个人觉得阅读官网的英文文档非常有助于理解各个IP特性&#xff09;。若有不对之处请参考参考文档&#xff0c;以官网文档为准。阅读该文章&#xff0c;可以先查看AArch64 Exception Model学习&…

消息队列-RockMQ-定时延时发送消息

定时延时发送消息 任务需要延迟一段时间再进行处理。 生产者 public class Producer {public static void main(String[] args) throws Exception {DefaultMQProducer producer new DefaultMQProducer("producer_group");producer.setNamesrvAddr("ip:9876&q…

【从零开始学技术】Fiddler 抓取 https 请求大全

1.Fiddler代理浏览器设置 注意浏览器代理区别 Chrome/IE浏览器使用的都是系统代理设置 在chrome浏览器的设置中搜索代理&#xff0c;可以看到 打开IE浏览器&#xff0c;选择设置->Internet选项 Firefox浏览器使用的是单独的一套代理系统 在Firefox的代理设置中&#xff0c;我…

hadoop自动获取时间

1、自动获取前15分钟 substr(from_unixtime(unix_timestamp(concat(substr(20240107100000,1,4),-,substr(20240107100000,5,2),-,substr(20240107100000,7,2), ,substr(20240107100000,9,2),:,substr(20240107100000,11,2),:,00))-15*60,yyyyMMddHHmmss),1) unix_timestam…

sentinel熔断简单实现

sentinel详细介绍网址 基于qps限流 package mainimport ("fmt"sentinel "github.com/alibaba/sentinel-golang/api""github.com/alibaba/sentinel-golang/core/base""github.com/alibaba/sentinel-golang/core/flow""log"…

CMake入门教程【核心篇】设置和使用缓存变量

😈「CSDN主页」:传送门 😈「Bilibil首页」:传送门 😈「动动你的小手」:点赞👍收藏⭐️评论📝 文章目录 概述设置缓存变量使用缓存变量更改缓存变量完整代码示例实战使用技巧注意事项总结与分析

STM32-04-STM32时钟树

STM32时钟树 什么是时钟&#xff1f; 时钟是具有周期性的脉冲信号&#xff0c;最常用的是占空比50%的方波。&#xff08;时钟是单片机的脉搏&#xff0c;搞懂时钟走向及关系&#xff0c;对单片机使用至关重要&#xff09;。 时钟树 时钟源 2个外部时钟源 高速外部振荡器(HSE…

Lava多模态大模型调试(基于vscode框架)

文章目录 前言一、整体概括二、launch.json文件配置三、调试展示前言 之前博客这里介绍LLava1.5多模态大模型的安装、训练、预测等。但对于你想查看源码或多或少都有些麻烦,也不利于代码调试。基于此,本文是一篇基于vscode框架调试llava大模型的教程。 一、整体概括 我是在…

再谈前端算法

楔子 – 青蛙跳台阶什么是算法算法实例 &#xff1a; 实现一个LRU缓存 实现 LRUCache扩展&#xff1a; ES6 Map Map的创建和初始化&#xff1a;添加键值对&#xff1a;获取键值对&#xff1a;检查Map中是否存在某个键&#xff1a;删除键值对&#xff1a;遍历Map&#xff1a;获取…

MulticoreWare与Imagination一同按下汽车计算工作负载的“加速键”

中国北京 – 2024年1月8日 - MulticoreWare Inc与Imagination Technologies共同宣布已在德州仪器TDA4VM处理器上实现了GPU计算&#xff0c;不仅使算力提升了约50 GFLOPS&#xff0c;而且还实现了自动驾驶和高级驾驶辅助系统&#xff08;ADAS&#xff09;常见工作负载性能的跃升…

环境变量的使用

1.用法 1.建立文件夹.env.production&#xff08;开发&#xff09;.env.development(生产) 代码: NODE_ENVdevelopment VUE_APP_BASE_APIwww.aaa.comNODE_ENVproduction VUE_APP_BASE_APIwww.xxx.com 注意: 环境变量的文件夹应该是和src目录同级的: 2.获取 process.env.V…

php环境搭建

PHP环境搭建 1.软件下载及安装 php网址&#xff1a;php.net vscode网址&#xff1a;https://code.visualstudio.com/ 百度网盘&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1kx_Z-2dz3kGozDcynW7C_Q 提取码&#xff1a;1234 PHP&#xff1a; PHP安装 解压到指定…

无线与局域网技术期末划题自制答案

简答题 1.描述5G的三大应用场景&#xff1f; 5G的三大应用场景包括增强型移动宽带&#xff08;eMBB&#xff09;、超可靠低延迟通信&#xff08;URLLC&#xff09;和大规模机器类型通信&#xff08;mMTC&#xff09;。增强型移动宽带&#xff08;eMBB&#xff09;主要用于支持…

2024.1.9每日一题

LeetCode 2707.字符串中的额外字符 2707. 字符串中的额外字符 - 力扣&#xff08;LeetCode&#xff09; 题目描述 给你一个下标从 0 开始的字符串 s 和一个单词字典 dictionary 。你需要将 s 分割成若干个 互不重叠 的子字符串&#xff0c;每个子字符串都在 dictionary 中出…

MongoDB 设置账号密码_mongodb设置用户名和密码

MongoDB 设置账号密码_mongodb设置用户名和密码 1、安装 安装可以看我这篇文章:https://blog.csdn.net/u014641168/article/details/123937775 2、说明 由于默认安装的MongoDB是没有设置用户密码的,极其危险,所以需要设置一下用户密码 3、创建用户 用Navicat15连接Mon…

【Python学习】Python学习9-字符串

目录 【Python学习】Python学习9-字符串 前言创建语法访问字符串的值字符串拼接Python 转义字符Python字符串运算符Python格式化字符串Python 三引号Unicode字符串Python 的字符串内建函数参考 文章所属专区 Python学习 前言 本章节主要说明Python的字符串类型。 创建语法 …

Linux【C编程】 信号以及信号的处理方式

文章目录 1.什么是信号&#xff1f;1.1信号是内容受限的一种异步通信机制1.2信号由谁发出的&#xff1f;1.3信号由谁处理&#xff0c;如何处理 2.常见的信号3.进程对信号的处理3.1用signal函数处理SIGINT信号3.2使用sigaction 函数 4.alarm 和pause函数4.1 alarm函数详解4.2 pa…

1.4.1机器学习——梯度下降+α学习率大小判定

1.4.1梯度下降 4.1、梯度下降的概念 ※【总结一句话】&#xff1a;系统通过自动的调节参数w和b的值&#xff0c;得到最小的损失函数值J。 如下&#xff1a;是梯度下降的概念图。 我们有一个损失函数 J(w,b)&#xff0c;包含两个参数w和b&#xff08;你可以想象成J(w,b) w*x…