数据结构——链表

news2024/11/15 3:32:59

目录

一、链表概述

二、模拟实现链表 

1、结点

         2、遍历链表

3、获取链表的长度 

4、添加元素 

(1)、头插法 

(2)、尾插法 

(3)、在指定位置插入元素 

5、删除元素 

 (1)、删除第一次出现值为key的结点

 (2)、删除所有值为key的结点

6、清空链表 

三、常见笔试题 

1、单链表转置

2、获取单链表的中间结点 

3、获取倒数第K个结点

4、合并两个有序链表 


一、链表概述

链表:存储结构上并非连续,元素之间靠指针连接的线性表。

链表可以分为是否带头节点的链表、是否为循环链表、是否为双向链表,但是不带头的单向链表使用较多,本文也是对不带头的单向链表进行详解。

二、模拟实现链表 

1、结点

链表是有多个结点组成,结点的成员变量有data和next,结点类为链表类的内部类。

class Node{
        public int data;
        public  Node next;
        public Node(int data){
            this.data=data;
        }
      }

2、遍历链表

定义一个结点指向链表的首元结点,逐个进行遍历,直至链表中某个结点的next为空。

//遍历链表
    public void display() {
        if(head==null){
            return;
        }
        Node cur=head;
        while(cur!=null){
            System.out.print(cur.data+" ");
            cur=cur.next;
        }
    }

3、获取链表的长度 

与遍历链表相似,只是需要设置一个计数器,来求出链表的长度。

 public int size() {
        int count=0;
        Node cur = head;
        while(cur!=null){
            count++;
            cur=cur.next;
        }
        return count;
    }

4、添加元素 

(1)、头插法 

将待添加的元素插入到链表首部,需要将待插的元素封装为一个结点,将该结点的next指向链表的首部,再将链表的首部指向该结点,那么该结点为链表的首元结点。

//头插法
    public void addFirst(int data) {
        Node node=new Node(data);
        node.next=head;
        head=node;
    }

(2)、尾插法 

将需要插入的元素封装为一个结点,遍历整个链表,让链表的最后一个结点的next指向新增的结点即可。

  

//尾插法
    public void addLast(int data) {
        Node node=new Node(data);
        if(head==null){
            head=node;
            return;
        }
        Node cur=head;
        while(cur.next!=null){
            cur=cur.next;
        }
        cur.next=node;

    }

(3)、在指定位置插入元素 

可以再定义一个方法获取指定位置的结点,以此得到指定位置的前一个结点,然后新增结点的next为前一个结点的next, 前一个结点的next为新增结点。

 

//获取指定位置的结点
    public Node indexNode(int index){
        if(index<0||index>size()){
            throw new PosException("位置不合法!");
        }
        int count=0;
        Node cur = head;
        while(count!=index){
            cur=cur.next;
            count++;
        }
        return cur;
    }
//任意位置插入,第一个数据节点为0号下标
    public boolean addIndex(int index, int data) {

       if(index==0){
           addFirst(data);
           return true;
       }
       if(index==size()){
           addLast(data);
           return true;
       }
       if(index<0||index>size()){
           throw new PosException("位置不合法!");
       }
       Node cur=indexNode(index-1);
       Node node=new Node(data);
       node.next=cur.next;
       cur.next=node;
       return true;
    }

5、删除元素 

 (1)、删除第一次出现值为key的结点

首先对特殊情况(链表为空,链表的首元结点为要删除的节点,直接将首元结点指向其下一个结点) 处理,然后找到key结点的前一个结点,让其的next指向next.next。

 

//删除第一次出现关键字为key的节点
    public void remove(int key) {
        if(head==null){
            return;
        }
        Node cur=head;
        if(cur.data==key&&cur.next==null){
            head=null;
            return;
        }
        while(cur.next!=null){
            if(cur.next.data==key){
                cur.next=cur.next.next;
                return;
            }
            cur=cur.next;
        }
        System.out.println("链表中不存在"+key+"元素");
    }

(2)、删除所有值为key的结点

首先仍需对特殊情况进行处理(与上述类似),采用双指针,开始时,pre和cur都指向首元结点, 当cur继续像后遍历时,若值为key,则pre.next=cur.next,否则pre=cur。

  

//删除所有值为key的结点
    public void removeAllKey(int key) {
        if(head==null){
            return;
        }
        while(head.data==key){
            if(head.next==null){
                head=null;
            }
            head=head.next;
        }
        Node pre=head;
        Node cur=head.next;
        while(cur!=null){
            if(cur.data==key){
                pre.next=cur.next;
                cur=cur.next;
            }else{
                pre=cur;
                cur=cur.next;
            }
        }
        /*if(head.data==key){
            if(head.next==null){
                head=null;
            }
            head=head.next;
        }*/
    }

6、清空链表 

直接将首元结点置为null即可。

public void clear() {
        head=null;
    }

三、常见笔试题 

 1、单链表转置

对链表为空和链表只有一个首元结点进行处理,定义一个结点cur指向首元结点的next,然后利用头插法的思想,将所有的元素进行转置。

public ListNode reverseList(ListNode head) {
         if(head==null){
            return null;
        }
        if(head.next==null){
            return head;
        }
        ListNode cur=head.next;
        head.next=null;
        while(cur!=null){
            ListNode node=cur.next;
            cur.next=head;
            head=cur;
            cur=node;
        }
        return head;
    }

2、获取单链表的中间结点 

同样需要对特殊情况进行处理,之后不再赘述,利用快慢指针的思想,在进行遍历时,slow向后走一步,fast向后走两步,这里需要考虑到链表长度为奇数和偶数的情况,对于奇数的

情况是fast.next==null,对于偶数的情况是fast==null,故将while的循环条件写为(fast!=null&&fast.next!=null)。

 

 

public ListNode middleNode(ListNode head) {
         if(head==null){
            return null;
        }
        if(head.next==null){
            return head;
        }
        ListNode slow=head.next;
        ListNode fast=head.next.next;
        while(fast!=null&&fast.next!=null){
            slow=slow.next;
            fast=fast.next.next;
        }
        return slow;
    }

3、获取倒数第K个结点

依旧采用快慢指针的思想,首先对k的合法性进行判断,先将fast和slow都指向head,然后将fast指向其后的k个结点,最后进行while循环,fast和slow继续向后进行遍历,循环条件为fast!=null,循环结束后slow指向倒数第k个结点。

 

public ListNode FindKthToTail(ListNode head,int k) {
        if(k<=0){
            return null;
        }
        if(head==null){
            return null;
        }

        ListNode slow=head;
        ListNode fast=head;
        int count=0;
        while(count<k){
            if(fast==null){
                return null;
            }
            fast=fast.next;
            count++;
        }
        while(fast!=null){
            slow=slow.next;
            fast=fast.next;
        }
        return slow;
    }

4、合并两个有序链表 

需要定义一个新的首元结点,再定义一个结点cur指向该结点然后对两个链表进行遍历,循环条件为两个链表不为空,较小的结点添加到cur结点之后,遍历完成后,若还有链表没有遍历完,则cur.next指向未遍历完链表的首元结点。最后将新链表的首元结点进行删除。

public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
        ListNode newHead=new ListNode(0);
        ListNode cur=newHead;
        while(list1!=null&&list2!=null){
            if(list1.val<list2.val){
                cur.next=list1;
                list1=list1.next;
            }else{
                cur.next=list2;
                list2=list2.next;
            }
            cur=cur.next;
        }
        if(list1!=null){
            cur.next=list1;
        }
        if(list2!=null){
            cur.next=list2;
        }
        newHead=newHead.next;
        return newHead;
    }

 5、判断链表是否为回文

首先需要找到中间结点,然后从中间结点的后一个改变指向,进行翻转,最后进行遍历。

 

public boolean chkPalindrome(ListNode head) {
         if(head==null){
            return false;
        }
        if(head.next==null){
            return true;
        }
        ListNode slow=head;
        ListNode fast=head;
        //1、寻找中间结点
        while(fast!=null&&fast.next!=null){
            fast=fast.next.next;
            slow=slow.next;
        }
        //2.翻转
        ListNode cur=slow.next;
        while(cur!=null){
            ListNode curNext=cur.next;
            cur.next=slow;
            slow=cur;//注意:此处不能写slow=slow.next,因为slow后面结点的next指向已发生改变
            cur=curNext;
        }
        //3.判断
        while(head!=slow){
            if(head.val!=slow.val){
                return false;
            }
            if(head.next==slow){
                return true;
            }
            head=head.next;
            slow=slow.next;
        }
        return true;
    }

 

 

 

 

 

 

 

 

 

 

 

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

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

相关文章

Springboot整合mybatis多数据源

Mybatis中如何配置多数据源 一 什么情况下会用到多数据库&#xff1f; 场景1&#xff1a; 一个商城网站&#xff0c;一个游戏网站&#xff0c;商城网站已经做好&#xff0c;游戏网站正在开发&#xff0c;游戏网站上的很多道具需要用到商城网站的产品数据&#xff0c;这种情况…

[附源码]Python计算机毕业设计Django基于JEE平台springboot技术的订餐系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

wy的leetcode刷题记录_Day57

wy的leetcode刷题记录_Day57 声明 本文章的所有题目信息都来源于leetcode 如有侵权请联系我删掉! 时间&#xff1a;2022-12-1 前言 leetcode 每日一题二叉树 1779. 找到最近的有相同 X 或 Y 坐标的点 701. 二叉搜索树中的插入操作 目录wy的leetcode刷题记录_Day57声明前言1…

多目标Jaya优化算法(Matlab代码实现)

👨‍🎓个人主页:研学社的博客 💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭:行百里者,半于九十。 📋📋📋本文目录如下:🎁🎁🎁 💥1 概述 多目标 Jaya 算…

CG-FX 风向传感器 聚碳 浅谈工作原理

产品概述 本产品外型小巧轻便&#xff0c;美观坚固&#xff0c;便于携带和组装&#xff0c;风向标形状设计合理&#xff0c;对自然界大气风向具有准确的定位作用。采用聚碳材质&#xff0c;具有防雨、防腐蚀、坚固实用等优点。 功能特点 ◆体积小&#xff0c;重量轻&#xf…

[附源码]Python计算机毕业设计Django绿色生鲜

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

[附源码]JAVA毕业设计酒店管理系统(系统+LW)

[附源码]JAVA毕业设计酒店管理系统&#xff08;系统LW&#xff09; 目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&…

anaconda使用系列教程--3)conda命令详解

管理conda 在任何时候你可以通过在命令后边跟上-help来获得该命令的完整文档。例如&#xff0c;你可以通过如下的命令来学习conda的update命令conda update --help Conda会返回你安装Anaconda软件的版本conda --version 升级当前版本conda update conda 查看当前conda信息cond…

[附源码]计算机毕业设计打印助手平台

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

[附源码]计算机毕业设计基于springboot的旅游景点管理系统的设计与实现

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

JSP+MySQL基于ssm的主题酒店管理系统

以往的主题酒店管理事务处理主要使用的是传统的人工管理方式,这种管理方式存在着管理效率低、操作流程繁琐、保密性差等缺点,长期的人工管理模式会产生大量的文本餐饮预订与文本数据,这对事务的查询、更新以及维护带来不少困难。随着互联网时代的到来,现如今网络的覆盖率已近非…

【WebRTC】QoS 拥塞控制 GCC 理论 Sender Side BWE 或 REMB

介绍 Sender Side Bandwidth Estimation 发送方带宽预估。Sender Side BWE 是新方案&#xff0c;利用的是 RTCP 中的 TransportCC 协议。 Receiver Estimated Maximum Bitrate 接收端预估最大码率。REMB 是旧方案&#xff0c;利用的是 RTCP 中的 REMB 协议。 背景 WebRTC 中…

C++自动定义的成员函数

C自动提供了下面这些成员函数&#xff1a; 默认构造函数&#xff0c;如果没有定义构造函数默认析构函数&#xff0c;如果没有定义复制构造函数&#xff0c;如果没有定义赋值运算符&#xff0c;如果没有定义地址运算符&#xff0c;如果没有定义 另有移动构造函数和移动赋值运算…

业余时间可以做什么副业,什么副业可以赚钱

大家好&#xff0c;我是蝶衣王的小编 现在的年轻人大多是过着朝九晚五的社畜生活&#xff0c;但是朝九晚五就意味着工资可能不是很高&#xff0c;生活压力会比较大&#xff0c;很多人就会想能不能利用业余时间做一些副业呢​&#xff1f;答案当然是可以的 那么&#xff0c;什…

售前工程师工作内幕揭秘:面试实战技巧

售前工程师工作内幕揭秘&#xff1a;面试实战技巧前言一、售前面试问题&#xff0c;基本就下面这些二、售前工程师岗位普遍误区三、售前工程师核心技能四、面试中&#xff0c;主动出击&#xff0c;才是王道五、对行业的了解是做好售前的基础前言 看到网上很多关于售前工程师面…

git分支上的tag

在发布一个版本时&#xff0c;我们通常先在版本库中打一个标签&#xff0c;这样&#xff0c;就唯一确定了打标签时刻的版本。将来无论什么时候&#xff0c;取某个标签的版本&#xff0c;就是把那个打标签的时刻的历史版本取出来。所以&#xff0c;标签也是版本库的一个快照。在…

Spring的创建与使用

⭐️前言⭐️ 在了解了Spring的核心与设计思想以后,下边就是Spring的具体使用&#xff0c;这篇文章主要介绍Spring项目的创建和Bean对象的存放与取出。 &#x1f349;博客主页&#xff1a; &#x1f341;【如风暖阳】&#x1f341; &#x1f349;精品Java专栏【JavaSE】、【备…

Kong(二)通过案例快速了解使用

一 Kong安装目录结构的说明 后续看看里面有啥 /usr/local/bin --> kong命令的路径/etc/kong/ --> kong默认会寻找配置文件/usr/local/kong --> Kong的日志 -->/usr/local/kong/logs/usr/local/lib/lua/5.1/usr/local/lib/…

[附源码]Python计算机毕业设计Django人事系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

【Leetcode】拿捏链表(五)——138. 复制带随机指针的链表

作者&#xff1a;一个喜欢猫咪的的程序员 专栏&#xff1a;《Leetcode》 喜欢的话&#xff1a;世间因为少年的挺身而出&#xff0c;而更加瑰丽。 ——《人民日报》 目录 138. 复制带随机指针的链表 138. 复制带随机指针的链表 138. 复制带随…