单链表的应用

链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的地址。

链表可分为单向链表和双向链表。本文只针对单链表进行说明。一个单链表的节点包含两个值:当前节点的值和指向下一个节点的链接。

基本结构就如上图所示,其中数值 1 所在的节点为链表的头节点,头节点的 value 域存储当前节点的值,next 域存储指向下一个节点的链接。

Java 中 LinkedList 与 ArrayList 类似,是一种常用的数据容器。提供了很多的常用方法:

LinkedList 常用方法
方法描述
public boolean add(E e)往链表末尾添加元素,即尾插,返回是否成功
public void add(int index, E e)向指定位置插入指定元素
public boolean addAll(Collection c)将一个集合的所有元素添加到链表尾部,返回是否成功
public boolean addAll(int index, Collection c)将一个集合的所有元素添加到链表的指定位置,返回是否成功
public void addFirst(E e)将元素添加到链表头部,即头插
public void addLast(E e)将元素添加到链表尾部,即尾插
public boolean offer(E e)向链表末尾添加元素,返回是否成功
public boolean offerFirst(E e)头部插入元素,返回是否成功
public boolean offerLast(E e)尾部插入元素,返回是否成功
public void clear()清空链表
public E removeFirst()删除并返回第一个元素
public E removeLast()删除并返回最后一个元素
public boolean remove(E e)删除指定元素,返回是否成功
public E remove(int index)删除指定位置的元素
public E poll()删除并返回第一个元素
public E remove()删除并返回第一个元素
public boolean contains(E e)判断链表中是否包含指定元素
public E get(int index)获取指定位置的元素
public E getFirst()获取第一个元素
public E getLast()获取最后一个元素
public int indexOf(E e)查找指定元素在链表中第一次出现的位置索引
public int lastIndexOf(E e)查找指定元素在链表中最后一次出现的位置索引
public E peek()获取第一个元素
public E element()获取第一个元素
public E peekFirst()获取头部元素
public E peekLast()获取尾部元素
public E set(int index, E e)设置指定位置的元素
public Object clone()复制该链表
public Iterator descendingIterator()返回倒序迭代器
public int size()获取链表元素个数
public ListIterator listIterator(int index)返回从指定位置开始到末尾的迭代器
public T[] toArray(T[] a)返回一个由链表元素转换类型而成的数组
public Object[] toArray()返回一个由链表元素组成的数组

其中有些获取元素、删除元素的方法我们在平时使用过程中并不会用到。

代码示例:

public static void main(String[] args) {
    List<Integer> list = new ArrayList() {{
        add(1);
        add(4);
        add(7);
        add(2);
        add(5);
        add(8);
    }};
    LinkedList linkedList = new LinkedList();
    // 将集合的所有元素添加到链表尾部
    linkedList.addAll(list);
    System.out.println("链表初始化:" + linkedList);
    // 向链表的头部插入元素 0
    linkedList.addFirst(0);
    System.out.println("头插元素0之后的链表为:" + linkedList);
    // 向链表的尾部插入元素 11
    linkedList.addLast(11);
    System.out.println("尾插元素11之后的链表为:" + linkedList);
    // 向链表的下标为 5 的位置插入元素 15
    linkedList.add(5, 15);
    System.out.println("指定位置插入元素15之后的链表为:" + linkedList);
    // 判断链表中是否包含元素15
    System.out.println("链表中是否包含元素15:" + linkedList.contains(15));
    // 获取链表中元素的个数
    System.out.println("该链表中元素的个数为:" + linkedList.size());
    // 获取链表头部元素
    System.out.println("链表头部元素为:" + linkedList.getFirst());
    // 获取链表尾部元素
    System.out.println("链表尾部元素为:" + linkedList.getLast());
}

执行结果为:

 一般来说,常用的方法就只有获取元素、计算元素个数、插入元素等。

自定义实现链表代码如下:

package com.xyy.insurance.web.service.impl;

/**
 * @ClassName: LinkedList
 * @Author: jiaoxian
 * @Date: 2021/9/8 16:00
 * @Description:
 */
public class LinkedList<Data> {

    /**
     * 头结点
     */
    private ListNode head;

    /**
     * 链表元素个数
     */
    private int size;

    public class ListNode {
        // 当前节点的值
        private Data value;
        // 指向下一个节点的链接
        private ListNode next;

        public ListNode(Data value, ListNode next) {
            this.value = value;
            this.next = next;
        }

        public ListNode(Data value) {
            this(value, null);
        }

        public ListNode() {
            this(null, null);
        }
    }

    /**
     * 无参构造函数
     */
    public LinkedList() {
        this.head = null;
        this.size = 0;
    }

    /**
     * 有参构造函数
     * @param size
     */
    public LinkedList(int size) {
        this.head = null;
        this.size = size;
    }

    /**
     * 获取链表元素的个数
     * @return
     */
    public int getSize() {
        return this.size;
    }

    /**
     * 判断链表是否为空
     * @return
     */
    public boolean isEmpty() {
        return this.size == 0;
    }

    /**
     * 往链表头部添加元素
     * @param value
     */
    public void addFirst(Data value) {
        // 要插入的节点对象
        ListNode node = new ListNode(value);
        node.next = this.head;
        this.head = node;
        this.size++;
    }

    /**
     * 向链表尾部插入元素
     * @param value
     */
    public void addLast(Data value) {
        this.add(value, this.size);
    }

    /**
     * 在指定位置插入元素
     * @param value
     * @param index
     */
    public void add(Data value, int index) {
        if (index < 0 || index > size) {
            throw new IllegalArgumentException("index is error");
        }
        if (index == 0) {
            this.addFirst(value);
            return;
        }
        ListNode preNode = this.head;
        // 找到要插入节点的前一个节点
        for (int i = 0; i < index - 1; i++) {
            preNode = preNode.next;
        }
        // 待插入的节点对象
        ListNode node = new ListNode(value);
        // 要插入的节点的下一个节点指向 preNode 节点的下一个节点
        node.next = preNode.next;
        // preNode 的下一个节点指向要插入节点
        preNode.next = node;
        this.size++;
    }

    /**
     * 删除链表元素
     * @param value
     */
    public void remove(Data value) {
        if (head == null) {
            System.out.println("无元素可删除");
            return;
        }
        // 要删除的元素与头结点的元素相同
        while (head != null && head.value.equals(value)) {
            head = head.next;
            this.size--;
        }
        ListNode cur = this.head;
        while (cur != null && cur.next != null) {
            if (cur.next.value.equals(value)) {
                this.size--;
                cur.next = cur.next.next;
            } else {
                cur = cur.next;
            }
        }

    }

    /**
     * 删除链表第一个元素
     * @return
     */
    public Data removeFirst() {
        if (this.head == null) {
            System.out.println("无元素可删除");
            return null;
        }
        ListNode delNode = this.head;
        this.head = this.head.next;
        delNode.next = null;
        this.size--;
        return delNode.value;
    }

    /**
     * 删除链表的最后一个元素
     * @return
     */
    public Data removeLast() {
        if (this.head == null) {
            System.out.println("无元素可删除");
            return null;
        }
        // 只有一个元素时
        if (this.getSize() == 1) {
            return this.removeFirst();
        }
        // 记录当前结点
        ListNode cur = this.head;
        // 记录要删除结点的前一个结点
        ListNode pre = this.head;
        while (cur.next != null) {
            pre = cur;
            cur = cur.next;
        }
        pre.next = cur.next;
        this.size--;
        return cur.value;
    }

    /**
     * 判断链表中是否包含某个元素
     * @param value
     * @return
     */
    public boolean contains(Data value) {
        ListNode cur = this.head;
        while (cur != null) {
            if (cur.value.equals(value)) {
                return true;
            } else {
                cur = cur.next;
            }
        }
        return false;
    }

    /**
     * 链表元素打印
     */
    public void display(){
        if (head == null) {
            System.out.println("empty");
        } else {
            ListNode cur = head;
            while (cur.next != null) {
                System.out.print(cur.value + " -> ");
                cur = cur.next;
            }
            System.out.println(cur.value);
        }
    }

    public LinkedList mergeTwoLists(LinkedList linkedList1, LinkedList linkedList2) {
        LinkedList linkedList = new LinkedList();
        ListNode cur = linkedList.head;
        ListNode listNode1 = linkedList1.head;
        ListNode listNode2 = linkedList2.head;
        while (listNode1 != null && listNode2 != null) {
            if ((Integer) listNode1.value < (Integer) listNode2.value) {
                cur.next = listNode1;
                cur = cur.next;
                listNode1 = listNode1.next;
                linkedList1.head = listNode1;
            } else {
                cur.next = listNode2;
                cur = cur.next;
                listNode2 = listNode2.next;
                linkedList2.head = listNode2;
            }
        }
        if (linkedList1 == null) {
            linkedList = linkedList2;
        } else {
            linkedList = linkedList1;
        }
        return linkedList;
    }

    public static void main(String[] args) {
        LinkedList linkedList1 = new LinkedList();
        linkedList1.addFirst(3);
        linkedList1.addFirst(2);
        linkedList1.addFirst(1);
        System.out.println("linkedList1 = " + linkedList1.getSize());
        linkedList1.display();
        LinkedList linkedList2 = new LinkedList();
        linkedList2.addLast(4);
        linkedList2.addLast(5);
        linkedList2.addLast(6);
        System.out.println("linkedList2 = " + linkedList2.getSize());
        linkedList2.display();
        LinkedList linkedList = new LinkedList();
        linkedList = linkedList.mergeTwoLists(linkedList1, linkedList2);
        linkedList.display();
//        linkedList.addLast(33);
//        linkedList.addFirst(33);
//        linkedList.add(33, 5);
//        System.out.println(linkedList);
//        linkedList.remove(33);
//        System.out.println(linkedList);
//        System.out.println("删除第一个元素:" + linkedList.removeFirst());
//        System.out.println(linkedList);
//        System.out.println("删除最后一个元素:" + linkedList.removeLast());
//        System.out.println(linkedList);
    }
}

参考文章:Java基础--单链表的实现_鱼非子-CSDN博客_java链表

Java单链表、双端链表、有序链表实现 - ㄓㄤㄑㄧㄤ - 博客园

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值