关于 Java 的数据结构链表

目录
  • 数据结构关于 Java 的链表
    • 1. 删除链表中等于给定值 val 的所有节点
    • 2. 反转一个单链表
    • 3. 给定一个带有头结点 head 的非空单链表
    • 4. 输入一个链表,输出该链表中倒数第k个结点
    • 5. 有序链表合并为一
    • 6. 编写代码
    • 7. 删除该链表中重复的结点
    • 8. 链表的回文结构
    • 9. 输入两个链表,找出它们的第一个公共结点
    • 10. 给定一个链表,判断链表中是否有环
    • 11. 给定一个链表

数据结构关于 Java 的链表

1. 删除链表中等于给定值 val 的所有节点

class Solution {
    public ListNode removeElements(ListNode head, int val) {
        if(head==null){
            return null;
        }
        ListNode prev=head;
        ListNode cur=head.next;
        while(cur!=null){
            if(cur.val==val){
                cur=cur.next;
                prev.next=cur;
            }else{
                prev=cur;
                cur=cur.next;
            }
        }
        if(head.val==val){
            head=head.next;
        }
        return head;
    }
}

2. 反转一个单链表

class Solution {
    public ListNode reverseList(ListNode head) {
        if(head==null || head.next==null){
            return head;
        }
        ListNode cur=head;
        ListNode newHead=null;
        while(cur!=null){
            ListNode curNext=cur.next;
            cur.next=newHead;
            newHead=cur;
            cur=curNext;
        }
        return newHead;
    }
}

方法: 头插法(从第二个节点开始对第一个节点进行头插)

注意:

  • 逆置不是只将数值反转,而是将节点本身进行逆置
  • 如果用前一章的 diplay 方法将逆置后的打印结果不正确,因为该 diplay 方法是从一开始定义的 head 节点开始打印,而现在真正的头节点已经改变,可以将其修改一下
public void display2(Node newHead){
    Node cur = newHead;
    while(cur!=null){
        System.out.print(cur.val + " ");
        cur=cur.next;
    }
    System.out.println();
}

3. 给定一个带有头结点 head 的非空单链表

给定一个带有头结点 head 的非空单链表,返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点

方法一:通过遍历找到节点数,然后找到中间节点

class Solution {
    public ListNode middleNode(ListNode head) {
        if(head==null){
            return null;
        }
        ListNode cur=head;
        int count=0;
        while(cur!=null){
            count++;
            cur=cur.next;
        }
        count=count/2+1;
        ListNode node=head;
        int i=0;
        while(i!=count-1){
            node=node.next;
            i++;
        }
        return node;
    }
}

方法二: 快慢指针法(快指针一次走两步,慢指针一次走一步)

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

4. 输入一个链表,输出该链表中倒数第k个结点

方法一:通过遍历找到节点数,然后找到倒数第 k 个节点

public class Solution {
    public ListNode FindKthToTail(ListNode head,int k) {
        if(head==null){
            return null;
        }
        ListNode cur = head;
        int count=0;
        while(cur!=null){
            count++;
            cur=cur.next;
        }
        if(k<1 || k>count){
            return null;
        }
        ListNode node = head;
        int i=0;
        while(i!=count-k){
            node=node.next;
            i++;
        }
        return node;
    }
}

方法二: 快慢指针法(先让快指针走 k-1 步,再让快慢指针同时走)

public class Solution {
    public ListNode FindKthToTail(ListNode head,int k) {
        if(head==null || k<=0){
            return null;
        }
        ListNode fast=head;
        ListNode slow=head;
        while(k-1!=0){
            fast=fast.next;
            if(fast==null){
                return null;
            }
            k--;
        }
        while(fast.next!=null){
            fast=fast.next;
            slow=slow.next;
        }
        return slow;
    }
}

5. 有序链表合并为一

将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的

class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        if(l1==null && l2==null){
            return null;
        }
        if(l1==null && l2!=null){
            return l2;
        }
        if(l2==null && l1!=null){
            return l1;
        }
        ListNode node=new ListNode();
        ListNode head=node;
        while(l1!=null && l2!=null){
            while(l1!=null && l2!=null && l1.val<=l2.val){
                node.next=l1;
                node=node.next;
                l1=l1.next;
            }
            while(l1!=null && l2!=null && l1.val>l2.val){
                node.next=l2;
                node=node.next;
                l2=l2.next;
            }
        }
        if(l1!=null){
            node.next=l1;
        }
        if(l2!=null){
            node.next=l2;
        }
        return head.next;
    }
}

6. 编写代码

以给定值x为基准将链表分割成两部分,所有小于x的结点排在大于或等于x的结点之前

public class Partition {
    public ListNode partition(ListNode pHead, int x) {
        if(pHead==null){
            return null;
        }
        ListNode cur=pHead;
        ListNode as=null;
        ListNode ae=null;
        ListNode bs=null;
        ListNode be=null;
        while(cur!=null){
            if(cur.val<x){
                if(bs==null){
                    bs=cur;
                    be=bs;
                }else{
                    be.next=cur;
                    be=be.next;
                }
            }else{
                if(as==null){
                    as=cur;
                    ae=as;
                }else{
                    ae.next=cur;
                    ae=ae.next;
                }
            }
            cur=cur.next;
        }
        if(bs==null){
            return as;
        }
        be.next=as;
        if(as!=null){
            ae.next=null;
        }
        return bs;
    }
}

其中 bs、be、as、ae,分别为小于 x 和大于 x 的两端的头尾节点

7. 删除该链表中重复的结点

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

public class Solution {
    public ListNode deleteDuplication(ListNode pHead) {
        if(pHead==null){
            return null;
        }
        ListNode node=new ListNode(0);
        ListNode newHead=node;
        ListNode cur=pHead;

        while(cur!=null){
            if(cur.next!=null && cur.val==cur.next.val){
                while(cur.next!=null && cur.val==cur.next.val){
                    cur=cur.next;
                }
                cur=cur.next;
            }else{
                newHead.next=cur;
                newHead=newHead.next;
                cur=cur.next;
            }
        }
        newHead.next=null;
        return node.next;
    }
}

8. 链表的回文结构

public class PalindromeList {
    public boolean chkPalindrome(ListNode A) {
        if(A==null){
            return true;
        }
        if(A.next==null){
            return true;
        }
        ListNode left=A;
        ListNode mid=A;
        ListNode right=A;
        while(right!=null && right.next!=null){
            right=right.next.next;
            mid=mid.next;
        }
        ListNode cur=mid.next;
        while(cur!=null){
            ListNode curNext=cur.next;
            cur.next=mid;
            mid=cur;
            cur=curNext;
        }
        while(mid!=left){
            if(mid.val!=left.val){
                return false;
            }
            if(left.next==mid){
                return true;
            }
            mid=mid.next;
            left=left.next;
        }
        return true;
    }
}

方法:

  • 找中间节点
  • 反转中间节点之后的链表
  • 将反转链表头尾进行比较

9. 输入两个链表,找出它们的第一个公共结点

public class Solution {
    public int getLength(ListNode head){
        if(head==null){
            return 0;
        }
        int count=0;
        while(head!=null){
            count++;
            head=head.next;
        }
        return count;
    }
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        if(headA==null || headB==null){
            return null;
        }
        ListNode cur1=headA;
        ListNode cur2=headB;
        int length1=getLength(headA);
        int length2=getLength(headB);
        int i=0;
        if(length1>=length2){
            while(i!=length1-length2){
                cur1=cur1.next;
                i++;
            }
        }else{
            while(i!=length2-length1){
                cur2=cur2.next;
                i++;
            }
        }
        while(cur1!=cur2){
            cur1=cur1.next;
            cur2=cur2.next;
        }
        return cur1;
    }
}

方法: 因为共同节点之后,两个链表的节点一样长。只要在共同节点之前,让两个链表移动的节点与公共节点距离相等,再一步一步移动即可

10. 给定一个链表,判断链表中是否有环

public class Solution {
    public boolean hasCycle(ListNode head) {
        if(head==null){
            return false;
        }
        if(head.next==null){
            return false;
        }
        ListNode fast=head;
        ListNode slow=head;
        while(fast!=null && fast.next!=null){
            fast=fast.next.next;
            slow=slow.next;
            if(fast==slow){
                return true;
            }
        }
        return false;
    }
}

方法: 快慢指针法(通过快指针追击慢指针,能追得上则有环)

11. 给定一个链表

给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null

public class Solution {
    public ListNode detectCycle(ListNode head) {
        if(head==null || head.next==null){
            return null;
        }
        ListNode fast=head;
        ListNode slow=head;
        while(fast!=null && fast.next!=null){
            fast=fast.next.next;
            slow=slow.next;
            if(fast==slow){
                break;
            }
        }
        if(fast==null || fast.next==null){
            return null;
        }
        fast=head;
        while(fast!=slow){
            fast=fast.next;
            slow=slow.next;
        }
        return fast;
    }

重点: 上述题中 fast=head ,以及后面代码含义就是找到公共节点之后,从该链表的头节点,以及交点,一起一步一步移动,当两个节点相遇时,则为第一个公共节点

分析: 上述重点不懂点可以结合下图分析理解

  • 当第一圈就追上时: 结论为 X=Y,所以两个节点每次移动一步就可
  • 当第 n 圈就追上时: 结论为 X=Y+(n-1)C。因为两个节点移动路程是一样的,并且交点那个节点移动 n-1 圈后,再要走 Y 正好到了起始节点。所以两个节点每次移动一步就可

到此这篇关于数据结构关于 Java 的链表详情的文章就介绍到这了,更多相关数据结构关于 Java 的链表内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java数据结构之链表相关知识总结

    一.链表 1.1 概述 链表是真正动态的数据结构,最简单的动态数据结构,基本用于辅助组成其他数据结构. 数据存储在"节点"(Node)中 优点:真正的动态,不需要处理固定容量的问题 缺点:丧失了随机访问的能力 1.2 链表使用的基本功能 定义Node节点 private class Node{ public E e; public Node next; public Node(E e, Node next){ this.e = e; this.next = next; } public

  • Java 单链表数据结构的增删改查教程

    我就废话不多说了,大家还是直接看代码吧~ package 链表; /** * *1)单链表的插入.删除.查找操作: * 2)链表中存储的是int类型的数据: **/ public class SinglyLinkedList { private Node head = null; //查找操作 public Node findByValue(int value){ Node p = head; //从链表头部开始查找 while(p.next != null && p.data != va

  • java 数据结构之删除链表中的元素实例代码

    java 删除链表中的元素 以下实例演示了使用 Clear() 方法来删除链表中的元素: import java.util.*; public class Main { public static void main(String[] args) { LinkedList<String> lList = new LinkedList<String>(); lList.add("1"); lList.add("8"); lList.add(&q

  • java数据结构基础:循环链表和栈

    目录 循环链表: 实现思路: 代码实现: 栈: 实现思路: 代码实现: 总结 循环链表: 与单链表的最后一个节点的指针域为null不同,循环链表的最后一个节点的指针指向头结点 实现思路: 初始化时将头结点指向自身,添加节点到链表末尾时,将新节点的指针指向头结点 在遍历链表时,判断是否遍历到链表末尾,需要判断当前指针的下一个节点是否为头结点 代码实现: 节点类CircleNode: public class CircleNode { public int data; public CircleNo

  • Java数据结构之简单链表的定义与实现方法示例

    本文实例讲述了Java数据结构之简单链表的定义与实现方法.分享给大家供大家参考,具体如下: 一.概述: 1.原理: 只有一个数据项(链接点Link),每个数据插入时都是对第一个数据的引用. 2.插入数据说明: 当链表没有数据时,插入的值就是第一个数据,如果链表里有数据,就把当前的数据的next指针指向第一个数据. 3.插入数据图: 4.特点:先进后出 5.实现功能: 数据插入,指定位置插入,显示,查询,删除等 6.删除原理 7.插入头节点原理 二.实现: 1.创建节点 /** * @描述 节点

  • 详解java数据结构与算法之双链表设计与实现

    在单链表分析中,我们可以知道每个结点只有一个指向后继结点的next域,倘若此时已知当前结点p,需要查找其前驱结点,那么就必须从head头指针遍历至p的前驱结点,操作的效率很低,因此如果p有一个指向前驱结点的next域,那效率就高多了,对于这种一个结点中分别包含了前驱结点域pre和后继结点域next的链表,称之为双链表.本篇我们将从以下结点来分析双链表 双链表的设计与实现 双链表的主要优点是对于任意给的结点,都可以很轻易的获取其前驱结点或者后继结点,而主要缺点是每个结点需要添加额外的next域,因

  • java 数据结构单链表的实现

    java 数据结构单链表的实现 单链表实现链表的打印及元素删除操作,链表的实现主要是next属性的定义,将一堆节点关联起来的.实现简单的链表如下: public class LinkNode { private int value; private LinkNode next; public LinkNode(int x) { value = x; } public LinkNode getNext(){ return next; } public void setNext(LinkNode n

  • Java数据结构之双端链表原理与实现方法

    本文实例讲述了Java数据结构之双端链表原理与实现方法.分享给大家供大家参考,具体如下: 一.概述: 1.什么时双端链表: 链表中保持这对最后一个连点引用的链表 2.从头部插入 要对链表进行判断,如果为空则设置尾节点为新添加的节点 3.从尾部进行插入 如果链表为空,则直接设置头节点为新添加的节点,否则设置尾节点的后一个节点为新添加的节点 4.从头部删除 判断节点是否有下个节点,如果没有则设置节点为null 二.具体实现 /** * @描述 头尾相接的链表 * @项目名称 Java_DataStr

  • 关于 Java 的数据结构链表

    目录 数据结构关于 Java 的链表 1. 删除链表中等于给定值 val 的所有节点 2. 反转一个单链表 3. 给定一个带有头结点 head 的非空单链表 4. 输入一个链表,输出该链表中倒数第k个结点 5. 有序链表合并为一 6. 编写代码 7. 删除该链表中重复的结点 8. 链表的回文结构 9. 输入两个链表,找出它们的第一个公共结点 10. 给定一个链表,判断链表中是否有环 11. 给定一个链表 数据结构关于 Java 的链表 1. 删除链表中等于给定值 val 的所有节点 class

  • Java数据结构之链表详解

    一.链表的介绍 什么是链表 链表是一种物理存储单元上非连续.非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的.链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成.每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域. 相比于线性表顺序结构,操作复杂.由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的

  • Java数据结构之单链表详解

    一.图示 二.链表的概念及结构 链表是一种物理存储结构上非连续存储结构,数据元素的逻辑顺序是通过链表中的引用链接次序实现的 . 实际中链表的结构非常多样,以下情况组合起来就有8种链表结构: 单向.双向 带头.不带头 循环.非循环 今天,我们实现的是一个 单向 无头 非循环的链表. 下面是此链表的结构组成. 三.单链表的实现 (1)定义一个节点类型 我们创建一个 ListNode 的类作为节点类型,那么我们如何定义成员属性呢? 通过上面的结构分析,我们需要定义两个成员变量 val --作为该节点的

  • java数据结构基础:单链表与双向链表

    目录 单链表: 实现思路: 代码实现: 双向链表: 实现思路: 代码实现: 总结 单链表: 每个数据是以节点的形式存在的 每个节点分为数据域和指针域 数据域中保存该节点的数据 指针域中保存指向下一个节点的指针 实现思路: 节点类SingleNode中保存数据和指向下一个节点的指针 单链表类SingleLinkedList中保存链表的头节点,实现相关链表方法 对于链表方法,涉及到位置查找,如在指定位置增加.删除节点,需要使用一个临时变量temp从头节点开始遍历,直至找到对应的位置. 对于节点的增加

  • Java数据结构之链表实现(单向、双向链表及链表反转)

    前言 之前学习的顺序表查询非常快,时间复杂度为O(1),但是增删改效率非常低,因为每一次增删改都会元素的移动.可以使用另一种存储方式-链式存储结构. 链表是一种物理存储单元上非连续.非顺序的存储结构.链表由一序列的结点(链表中的每一个元素成为结点)组成. 结点API设计: 类名 Node 构造方法 Node(T t,Node next) 创建Node对象 成员变量 T item:存储数据 Node next :指向下一个结点 结点类: public class Node<T>{ Node ne

  • Java描述数据结构学习之链表的增删改查详解

    前言 链表是一种常见的基础数据结构,它是一种线性表,但在内存中它并不是顺序存储的,它是以链式进行存储的,每一个节点里存放的是下一个节点的"指针".在Java中的数据分为引用数据类型和基础数据类型,在Java中不存在指针的概念,但是对于链表而言的指针,指的就是引用数据类型的地址. 链表和数组都是线性的数据结构,对于数组而言其长度是固定的,由于在内存中其是连续的,因此更适合做查找与遍历,而链表在内存中是并不是顺序存储的,但是由于其是通过"指针"构成的,因此在插入.删除时

  • java数据结构基础:单,双向链表

    目录 单向链表 单链表图解 代码 双向链表 编码 总结 单向链表 单向链表比顺序结构的线性表最大的好处就是不用保证存放的位置,它只需要用指针去指向下一个元素就能搞定. 单链表图解 图画的比较粗糙,简单的讲解一下: 上面四个长方形,每个长方形都是一个节点.在长方形中,一种包含两个东西,一个是当前节点的元素,一个是指向下一节点的地址.这个下一个节点的地址指向了下一个节点中的元素.以此类推. 在最左边的叫做头节点,同样,最后面的叫尾节点. 所以,我们所有的操作都是根据节点来进行操作. 代码 这些代码都

随机推荐