Java实现链表

一、什么是链表

链表是一种常用的线性数据结构,它由一系列结点(Node)组成。每个结点包含数据域和指针域,其中数据域存储结点的数据信息,指针域存储下一个结点的地址。链表中的结点可以在任何时间动态添加或删除。

二、链表的分类

链表可以分为单向链表、双向链表和循环链表三种类型。

  • 单向链表: 每个结点只有一个指针域,指向下一结点。
  • 双向链表: 每个结点有两个指针域,分别指向前驱结点和后继结点。
  • 循环链表: 单向循环链表和双向循环链表是两种形式的循环链表,它们的规则都是把链表的头结点和尾结点相连从而形成一个环。

三、Java实现单向链表

下面的代码展示了如何使用Java实现单向链表:

class Node {  
    // 数据域  
    private int data;  
    // 指针域  
    private Node next;  
  
    public Node(int data, Node next) {  
        this.data = data;  
        this.next = next;  
    }  
  
    public int getData() {  
        return data;  
    }  
  
    public void setData(int data) {  
        this.data = data;  
    }  
  
    public Node getNext() {  
        return next;  
    }  
  
    public void setNext(Node next) {  
        this.next = next;  
    }  
}  
  
class LinkedList {  
    // 头结点  
    private Node head;  
    // 链表长度  
    private int size;  
  
    public LinkedList() {  
        // 初始化头结点,next指向null  
        head = new Node(0, null);  
        size = 0;  
    }  
  
    // 根据index获取结点  
    private Node getNode(int index) {  
        if (index = size) {  
            throw new IndexOutOfBoundsException();  
        }  
        Node node = head.getNext();  
        for (int i = 0; i < index; i++) {  
            node = node.getNext();  
        }  
        return node;  
    }  
  
    // 插入结点  
    public void add(int index, int data) {  
        if (index  size) {  
            throw new IndexOutOfBoundsException();  
        }  
        Node prev = head;  
        for (int i = 0; i < index; i++) {  
            prev = prev.getNext();  
        }  
        Node node = new Node(data, prev.getNext());  
        prev.setNext(node);  
        size++;  
    }  
  
    // 删除结点  
    public void remove(int index) {  
        if (index = size) {  
            throw new IndexOutOfBoundsException();  
        }  
        Node prev = head;  
        for (int i = 0; i < index; i++) {  
            prev = prev.getNext();  
        }  
        Node node = prev.getNext();  
        prev.setNext(node.getNext());  
        size--;  
    }  
  
    // 修改结点  
    public void set(int index, int data) {  
        if (index = size) {  
            throw new IndexOutOfBoundsException();  
        }  
        Node node = getNode(index);  
        node.setData(data);  
    }  
  
    // 获取链表长度  
    public int getSize() {  
        return size;  
    }  
  
    // 获取结点数据  
    public int get(int index) {  
        if (index = size) {  
            throw new IndexOutOfBoundsException();  
        }  
        Node node = getNode(index);  
        return node.getData();  
    }  
} 

上面的代码中,LinkedList类包含了add、remove、set、getSize和get方法,分别实现了插入结点、删除结点、修改结点、获取链表长度和获取结点数据的功能。同时,Node类表示链表的每个结点,包含数据域和指针域。

四、Java实现双向链表

双向链表由于结点有前驱结点和后继结点两个指针域,所以需要在Node类中添加前驱指针域prev。同时,在链表插入和删除操作时还需要处理前驱结点的后继指针。

下面的代码展示了如何使用Java实现双向链表:

class Node {  
    // 数据域  
    private int data;  
    // 前驱指针域  
    private Node prev;  
    // 后继指针域  
    private Node next;  
  
    public Node(int data, Node prev, Node next) {  
        this.data = data;  
        this.prev = prev;  
        this.next = next;  
    }  
  
    public int getData() {  
        return data;  
    }  
  
    public void setData(int data) {  
        this.data = data;  
    }  
  
    public Node getPrev() {  
        return prev;  
    }  
  
    public void setPrev(Node prev) {  
        this.prev = prev;  
    }  
  
    public Node getNext() {  
        return next;  
    }  
  
    public void setNext(Node next) {  
        this.next = next;  
    }  
}  
  
class DoublyLinkedList {  
    // 头结点  
    private Node head;  
    // 尾结点  
    private Node tail;  
    // 链表长度  
    private int size;  
  
    public DoublyLinkedList() {  
        // 初始化头结点和尾结点,prev和next分别指向null  
        head = new Node(0, null, null);  
        tail = new Node(0, head, null);  
        head.setNext(tail);  
        size = 0;  
    }  
  
    // 根据index获取结点  
    private Node getNode(int index) {  
        if (index = size) {  
            throw new IndexOutOfBoundsException();  
        }  
        Node node;  
        if (index < size / 2) {  
            // 从前往后遍历  
            node = head.getNext();  
            for (int i = 0; i  index; i--) {  
                node = node.getPrev();  
            }  
        }  
        return node;  
    }  
  
    // 插入结点  
    public void add(int index, int data) {  
        if (index  size) {  
            throw new IndexOutOfBoundsException();  
        }  
        Node next = getNode(index);  
        Node prev = next.getPrev();  
        Node node = new Node(data, prev, next);  
        prev.setNext(node);  
        next.setPrev(node);  
        size++;  
    }  
  
    // 删除结点  
    public void remove(int index) {  
        if (index = size) {  
            throw new IndexOutOfBoundsException();  
        }  
        Node node = getNode(index);  
        Node prev = node.getPrev();  
        Node next = node.getNext();  
        prev.setNext(next);  
        next.setPrev(prev);  
        size--;  
    }  
  
    // 修改结点  
    public void set(int index, int data) {  
        if (index = size) {  
            throw new IndexOutOfBoundsException();  
        }  
        Node node = getNode(index);  
        node.setData(data);  
    }  
  
    // 获取链表长度  
    public int getSize() {  
        return size;  
    }  
  
    // 获取结点数据  
    public int get(int index) {  
        if (index = size) {  
            throw new IndexOutOfBoundsException();  
        }  
        Node node = getNode(index);  
        return node.getData();  
    }  
} 

上面的代码中,DoublyLinkedList类包含了add、remove、set、getSize和get方法,和LinkedList类相比需要多处理前驱指针和后继指针的更新。同时,Node类表示链表的每个结点,包含数据域、前驱指针域和后继指针域。

五、Java实现循环链表

循环链表在单向链表和双向链表的基础上,把链表的头结点和尾结点相连从而形成一个环。在插入和删除结点时,如果操作的位置是头结点或尾结点则需要更新尾结点和头结点的指针。

下面的代码展示了如何使用Java实现单向循环链表:

class Node {  
    // 数据域  
    private int data;  
    // 指针域  
    private Node next;  
  
    public Node(int data, Node next) {  
        this.data = data;  
        this.next = next;  
    }  
  
    public int getData() {  
        return data;  
    }  
  
    public void setData(int data) {  
        this.data = data;  
    }  
  
    public Node getNext() {  
        return next;  
    }  
  
    public void setNext(Node next) {  
        this.next = next;  
    }  
}  
  
class CircularLinkedList {  
    // 头结点  
    private Node head;  
    // 链表长度  
    private int size;  
  
    public CircularLinkedList() {  
        // 初始化头结点,next指向自身  
        head = new Node(0, null);  
        head.setNext(head);  
        size = 0;  
    }  
  
    // 根据index获取结点  
    private Node getNode(int index) {  
        if (index = size) {  
            throw new IndexOutOfBoundsException();  
        }  
        Node node = head.getNext();  
        for (int i = 0; i < index; i++) {  
            node = node.getNext();  
        }  
        return node;  
    }  
  
    // 插入结点  
    public void add(int index, int data) {  
        if (index  size) {  
            throw new IndexOutOfBoundsException();  
        }  
        if (index == size) {  
            // 插入尾结点  
            Node tail = head;  
            for (int i = 0; i < size; i++) {  
                tail = tail.getNext();  
            }  
            Node node = new Node(data, head);  
            tail.setNext(node);  
        } else {  
            Node prev = head;  
            for (int i = 0; i < index; i++) {  
                prev = prev.getNext();  
            }  
            Node node = new Node(data, prev.getNext());  
            prev.setNext(node);  
        }  
        size++;  
    }  
  
    // 删除结点  
    public void remove(int index) {  
        if (index = size) {  
            throw new IndexOutOfBoundsException();  
        }  
        if (index == size - 1) {  
            // 删除尾结点  
            Node tail = head;  
            for (int i = 0; i < size; i++) {  
                tail = tail.getNext();  
            }  
            Node prev = getNode(index - 1);  
            prev.setNext(head);  
            tail = prev;  
        } else {  
            Node prev = head;  
            for (int i = 0; i < index; i++) {  
                prev = prev.getNext();  
            }  
            Node node = prev.getNext();  
            prev.setNext(node.getNext());  
        }  
        size--;  
    }  
  
    // 修改结点  
    public void set(int index, int data) {  
        if (index = size) {  
            throw new IndexOutOfBoundsException();  
        }  
        Node node = getNode(index);  
        node.setData(data);  
    }  
  
    // 获取链表长度  
    public int getSize() {  
        return size;  
    }  
  
    // 获取结点数据  
    public int get(int index) {  
        if (index = size) {  
            throw new IndexOutOfBoundsException();  
        }  
        Node node = getNode(index);  
        return node.getData();  
    }  
} 

上面的代码中,CircularLinkedList类包含了add、remove、set、getSize和get方法,和LinkedList类相比需要多处理尾结点的指针。同时,Node类表示链表的每个结点,包含数据域和指针

原创文章,作者:小蓝,如若转载,请注明出处:https://www.506064.com/n/302730.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
小蓝小蓝
上一篇 2024-12-31 11:48
下一篇 2024-12-31 11:48

相关推荐

  • Java JsonPath 效率优化指南

    本篇文章将深入探讨Java JsonPath的效率问题,并提供一些优化方案。 一、JsonPath 简介 JsonPath是一个可用于从JSON数据中获取信息的库。它提供了一种DS…

    编程 2025-04-29
  • java client.getacsresponse 编译报错解决方法

    java client.getacsresponse 编译报错是Java编程过程中常见的错误,常见的原因是代码的语法错误、类库依赖问题和编译环境的配置问题。下面将从多个方面进行分析…

    编程 2025-04-29
  • Java Bean加载过程

    Java Bean加载过程涉及到类加载器、反射机制和Java虚拟机的执行过程。在本文中,将从这三个方面详细阐述Java Bean加载的过程。 一、类加载器 类加载器是Java虚拟机…

    编程 2025-04-29
  • Java腾讯云音视频对接

    本文旨在从多个方面详细阐述Java腾讯云音视频对接,提供完整的代码示例。 一、腾讯云音视频介绍 腾讯云音视频服务(Cloud Tencent Real-Time Communica…

    编程 2025-04-29
  • Java Milvus SearchParam withoutFields用法介绍

    本文将详细介绍Java Milvus SearchParam withoutFields的相关知识和用法。 一、什么是Java Milvus SearchParam without…

    编程 2025-04-29
  • 利用Python实现两个链表合并为一个有序链表

    对于开发工程师来说,实现两个链表合并为一个有序链表是必须掌握的技能之一。Python语言在链表处理上非常便利,本文将从多个方面详细阐述如何利用Python实现两个链表合并为一个有序…

    编程 2025-04-29
  • Java 8中某一周的周一

    Java 8是Java语言中的一个版本,于2014年3月18日发布。本文将从多个方面对Java 8中某一周的周一进行详细的阐述。 一、数组处理 Java 8新特性之一是Stream…

    编程 2025-04-29
  • Java判断字符串是否存在多个

    本文将从以下几个方面详细阐述如何使用Java判断一个字符串中是否存在多个指定字符: 一、字符串遍历 字符串是Java编程中非常重要的一种数据类型。要判断字符串中是否存在多个指定字符…

    编程 2025-04-29
  • VSCode为什么无法运行Java

    解答:VSCode无法运行Java是因为默认情况下,VSCode并没有集成Java运行环境,需要手动添加Java运行环境或安装相关插件才能实现Java代码的编写、调试和运行。 一、…

    编程 2025-04-29
  • Java任务下发回滚系统的设计与实现

    本文将介绍一个Java任务下发回滚系统的设计与实现。该系统可以用于执行复杂的任务,包括可回滚的任务,及时恢复任务失败前的状态。系统使用Java语言进行开发,可以支持多种类型的任务。…

    编程 2025-04-29

发表回复

登录后才能评论