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

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

链表是一种非常常用的数据结构,它有许多实际应用,比如链表可以用来实现栈、队列、散列表和图等数据结构。在Java语言中,链表的实现方式主要有单向链表、双向链表和循环链表。

单向链表

单向链表是一种链表结构,每个节点包含两个元素:节点值和一个指向下一个节点的引用。链表的头结点(第一个节点)不包含值,仅包含指向链表中第一个实际节点的引用。

单向链表的实现示例如下:

public class SingleLinkedList {
    private Node head; // 头结点,不包含值
    private int size; // 链表长度

    // 内部类Node,封装链表节点的值和next引用
    private class Node {
        Object value; // 节点的值
        Node next; // 指向下一个节点的引用

        public Node(Object value) {
            this.value = value;
        }
    }

    // 在头部插入节点
    public void addFirst(Object value) {
        Node newNode = new Node(value);
        newNode.next = head;
        head = newNode;
        size++;
    }

    // 在尾部插入节点
    public void addLast(Object value) {
        Node newNode = new Node(value);
        if (head == null) {
            head = newNode;
        } else {
            Node current = head;
            while (current.next != null) {
                current = current.next;
            }
            current.next = newNode;
        }
        size++;
    }

    // 在指定位置插入节点
    public void add(int index, Object value) {
        if (index < 0 || index > size) {
            throw new IndexOutOfBoundsException();
        }
        if (index == 0) {
            addFirst(value);
        } else if (index == size) {
            addLast(value);
        } else {
            Node newNode = new Node(value);
            Node current = head;
            for (int i = 0; i < index - 1; i++) {
                current = current.next;
            }
            newNode.next = current.next;
            current.next = newNode;
            size++;
        }
    }

    // 删除头节点,返回删除的节点值
    public Object removeFirst() {
        if (head == null) {
            throw new NoSuchElementException();
        }
        Object value = head.value;
        head = head.next;
        size--;
        return value;
    }

    // 删除尾节点,返回删除的节点值
    public Object removeLast() {
        if (head == null) {
            throw new NoSuchElementException();
        }
        if (head.next == null) {
            Object value = head.value;
            head = null;
            size--;
            return value;
        }
        Node current = head;
        while (current.next.next != null) {
            current = current.next;
        }
        Object value = current.next.value;
        current.next = null;
        size--;
        return value;
    }

    // 删除指定位置的节点,返回删除的节点值
    public Object remove(int index) {
        if (index < 0 || index >= size) {
            throw new IndexOutOfBoundsException();
        }
        if (index == 0) {
            return removeFirst();
        } else if (index == size - 1) {
            return removeLast();
        } else {
            Node current = head;
            for (int i = 0; i < index - 1; i++) {
                current = current.next;
            }
            Object value = current.next.value;
            current.next = current.next.next;
            size--;
            return value;
        }
    }

    // 获取链表长度
    public int size() {
        return size;
    }

    // 获取指定位置的节点值
    public Object get(int index) {
        if (index < 0 || index >= size) {
            throw new IndexOutOfBoundsException();
        }
        Node current = head;
        for (int i = 0; i < index; i++) {
            current = current.next;
        }
        return current.value;
    }
}

双向链表

双向链表是一种链表结构,每个节点包含三个元素:前一个节点的引用、节点值和下一个节点的引用。链表的头结点(第一个节点)和尾节点(最后一个节点)都存在。

双向链表的实现示例如下:

public class DoubleLinkedList {
    private Node head; // 头结点,不包含值
    private Node tail; // 尾节点,不包含值
    private int size; // 链表长度

    // 内部类Node,封装链表节点的值、prev引用和next引用
    private class Node {
        Object value; // 节点的值
        Node prev; // 指向前一个节点的引用
        Node next; // 指向下一个节点的引用

        public Node(Object value) {
            this.value = value;
        }
    }

    // 在头部插入节点
    public void addFirst(Object value) {
        Node newNode = new Node(value);
        if (head != null) {
            head.prev = newNode;
        } else {
            tail = newNode;
        }
        newNode.next = head;
        head = newNode;
        size++;
    }

    // 在尾部插入节点
    public void addLast(Object value) {
        Node newNode = new Node(value);
        if (head == null) {
            head = newNode;
        } else {
            tail.next = newNode;
            newNode.prev = tail;
        }
        tail = newNode;
        size++;
    }

    // 在指定位置插入节点
    public void add(int index, Object value) {
        if (index < 0 || index > size) {
            throw new IndexOutOfBoundsException();
        }
        if (index == 0) {
            addFirst(value);
        } else if (index == size) {
            addLast(value);
        } else {
            Node newNode = new Node(value);
            Node current = head;
            for (int i = 0; i < index - 1; i++) {
                current = current.next;
            }
            newNode.next = current.next;
            newNode.prev = current;
            current.next.prev = newNode;
            current.next = newNode;
            size++;
        }
    }

    // 删除头节点,返回删除的节点值
    public Object removeFirst() {
        if (head == null) {
            throw new NoSuchElementException();
        }
        Object value = head.value;
        head = head.next;
        if (head != null) {
            head.prev = null;
        } else {
            tail = null;
        }
        size--;
        return value;
    }

    // 删除尾节点,返回删除的节点值
    public Object removeLast() {
        if (head == null) {
            throw new NoSuchElementException();
        }
        Object value = tail.value;
        tail = tail.prev;
        if (tail != null) {
            tail.next = null;
        } else {
            head = null;
        }
        size--;
        return value;
    }

    // 删除指定位置的节点,返回删除的节点值
    public Object remove(int index) {
        if (index < 0 || index >= size) {
            throw new IndexOutOfBoundsException();
        }
        if (index == 0) {
            return removeFirst();
        } else if (index == size - 1) {
            return removeLast();
        } else {
            Node current = head;
            for (int i = 0; i < index - 1; i++) {
                current = current.next;
            }
            Object value = current.next.value;
            current.next = current.next.next;
            current.next.prev = current;
            size--;
            return value;
        }
    }

    // 获取链表长度
    public int size() {
        return size;
    }

    // 获取指定位置的节点值
    public Object get(int index) {
        if (index < 0 || index >= size) {
            throw new IndexOutOfBoundsException();
        }
        Node current = head;
        for (int i = 0; i < index; i++) {
            current = current.next;
        }
        return current.value;
    }
}

示例说明

示例一

SingleLinkedList list = new SingleLinkedList();
list.addFirst(1); // 在头部插入节点
list.addLast(3); // 在尾部插入节点
list.add(1, 2); // 在指定位置插入节点
System.out.println(list.size()); // 获取链表长度
System.out.println(list.get(0)); // 获取第一个节点的值
System.out.println(list.get(1)); // 获取第二个节点的值
System.out.println(list.get(2)); // 获取第三个节点的值

以上代码输出的结果是:

3
1
2
3

示例二

DoubleLinkedList list = new DoubleLinkedList();
list.addFirst(1); // 在头部插入节点
list.addLast(3); // 在尾部插入节点
list.add(1, 2); // 在指定位置插入节点
System.out.println(list.size()); // 获取链表长度
System.out.println(list.get(0)); // 获取第一个节点的值
System.out.println(list.get(1)); // 获取第二个节点的值
System.out.println(list.get(2)); // 获取第三个节点的值

以上代码输出的结果是:

3
1
2
3

以上就是Java数据结构之链表相关知识的总结,希望对大家有所帮助!

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java数据结构之链表相关知识总结 - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • 解析Facebook的数据库查询引擎Presto在美团的应用

    解析Facebook的数据库查询引擎Presto在美团的应用 什么是Presto? Presto是一个面向分布式查询的数据引擎,由Facebook开发并开源。它支持SQL查询,可以在不同类型的数据源中查询数据(如Hadoop HDFS、Hive等),具有快速、可扩展、灵活等特点。 Presto在美团的应用 美团使用Presto来进行大数据分析,帮助其优化运营…

    数据结构 2023年5月17日
    00
  • C语言中数据结构之链式基数排序

    C语言中数据结构之链式基数排序 概述 链式基数排序是基数排序的一种实现方式。基数排序是一种桶排序算法,它通过将需要排序的数据分成多个桶,并且按照一定的顺序将数据从桶中取出来,以达到排序的目的。链式基数排序则使用了链表结构来实现桶的功能。 实现步骤 链式基数排序的实现步骤如下: 申请链表节点数组,并初始化链表头结点数组。链表的数量等于指定的基数,例如10进制的…

    数据结构 2023年5月17日
    00
  • C++抽象数据类型介绍

    C++抽象数据类型介绍 什么是抽象数据类型? 抽象数据类型(Abstract Data Type,ADT),是数据类型的一个数学模型。它实现了数据类型的抽象过程,将数据与操作分离,使得操作具有独立性,而数据只作为函数参数和返回值存在。 举个例子,ADT可以定义一个栈(Stack),栈的实现需要以下操作: 初始化栈 压入数据 弹出数据 获取栈顶数据 检查栈是否…

    数据结构 2023年5月17日
    00
  • JavaScript数据结构之广义表的定义与表示方法详解

    JavaScript数据结构之广义表的定义与表示方法详解 什么是广义表 广义表是一种包含了无数元素的数据结构,可以是元素或者嵌套的子表。广义表可以表示为: $\quad\quad\quad GL = (a_0,a_1,…,a_n)$ 其中$a_i$可以是元素或者一个子表,如果$a_i$为一个子表,那么$a_i$本身也是一个广义表。广义表中,第一个元素$a…

    数据结构 2023年5月17日
    00
  • Java数据结构二叉树难点解析

    Java数据结构二叉树难点解析 什么是二叉树 二叉树是一种非常常见的数据结构,它具有以下特点: 每个节点都最多有两个子节点。 左子节点的值小于等于父节点的值,右子节点的值大于等于父节点的值。 二叉树可以用递归的方式实现,如下所示: class TreeNode { int val; TreeNode left; TreeNode right; TreeNod…

    数据结构 2023年5月17日
    00
  • Java数据结构之常见排序算法(下)

    Java数据结构之常见排序算法(下) 前言 这是 Java 数据结构之常见排序算法的第二篇,本篇文章将继续介绍常见的排序算法。对于尚未了解基本排序算法的读者,可以先阅读 Java 数据结构之常见排序算法(上)。 快速排序 快速排序是一种使用分治思想的排序算法,其思路是将一个数组分为两个子数组,再对子数组进行排序,这个过程不断递归执行。在具体实现时,选择一个元…

    数据结构 2023年5月17日
    00
  • 实际问题中用到的算法——递归算法确定插帧顺序

    问题: 现在需要给一个视频序列插帧,插帧算法要求每次只能由两帧输入插值得到其中间帧。如果现在需要给一个视频做 4 倍(或者更高的 8,16 倍等类似)的插帧,则一个插帧的思路是当前视频每相邻帧之间插入 3 帧,即:假设插帧前视频帧序号是 0,4,8,12…,则插帧时补充相邻帧跨过的 3 个序号,得到插帧后的视频帧序号为 0,1,2,3,4,5,6,.. 即可…

    算法与数据结构 2023年4月18日
    00
  • Java数据结构学习之二叉树

    Java数据结构学习之二叉树 什么是二叉树 二叉树是一种树形数据结构,他的每个节点最多有两个子节点,分别称为左子节点和右子节点。如果一个节点没有子节点,则成为叶子节点。二叉树具有以下性质: 每个节点最多有两个子节点 左子树和右子树是二叉树 二叉树可以为空 二叉树的遍历 为了遍历一棵树,我们可以采用两种算法: 深度优先遍历 深度优先遍历的思路是:从根节点出发,…

    数据结构 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部