【Java实现链表基本操作】

一、链表的基础定义

链表是线性表的一种,但在内存中不一定是连续存储的,而是可以存在于内存中未被占用的任意位置。基于此,链表这种数据结构,除了要存储数据元素的信息外,还需要存储它的后继元素的存储地址。

在这里插入图片描述
链表中几个重要概念:
结点——链表所占用的一个内存块,一个结点包括数据域和指针域两部分。数据域用于存储数据信息data,指针域用于存储下个结点的地址next,通常叫做后继指针。
头结点——链表中的第一个结点,只要知道了头结点在内存中的地址,就可根据其指针域存储的下一个结点的地址找到下一个结点。
尾结点——链表中的最后一个结点,由于是链表中的最后一个结点,它的指针域存储的不是下一个结点的地址而是NULL,以此来表示是链表的尾结点。

二、Java中定义一个数据节点

    private class Node {
        //数据域
        T data;
        //指针域
        Node next;

        public Node(T data, Node next) {
            this.data = data;
            this.next = next;
        }

        public Node(T data) {
            this.data = data;
        }

        @Override
        public String toString() {
            return "Node{" +
                    "data=" + data +
                    ", next=" + next +
                    '}';
        }
    }

三、查找特定位置的链表节点

    public Node get(int index) {
        if (index < 0 || index >= size) {
            return null;
        } else {
            Node temp = head;
            //从头结点开始遍历至index位置
            for (int i = 0; i < index; i++) {
                temp = temp.next;
            }
            return temp;
        }
    }

四、向链表指定位置添加新的结点

    public void insert(int index, T data) {
        if (index < 0 || index > size) {
            throw new RuntimeException("插入超出范围");
        }
        Node newNode = new Node(data);
        //头插
        if (index == 0) {
            if (this.size > 0) {
                newNode.next = head;
            }
            head = newNode;
        }
        //尾插
        else if (index == size) {
            tail.next = newNode;
            tail = newNode;
        } else {
            //获取要插入位置的前一个节点
            Node preNode = get(index - 1);
            //将要当前节点的指针指向前一个节点的下一个节点
            newNode.next = preNode.next;
            //将前一个节点的指针指向当前节点
            preNode.next = newNode;
        }
        size++;
        if (size == 1) {
            tail = head;
        }
    }

五、在链表末尾添加新的节点

    public void add(T data) {
        Node newNode = new Node(data);
        //长度为0证明
        if (size == 0) {
            head = newNode;
            tail = head;
        } else {
            tail.next = newNode;
            tail = newNode;
        }
        size++;
    }

六、删除指定位置的节点

    public void del(int index) {
        if (index < 0 || index >= size) {
            throw new RuntimeException("删除超出范围");
        }
        if (index == 0) {
            head = head.next;
        } else if (index == size - 1) {
            Node preNode = get(size - 1);
            tail = preNode;
            preNode.next = null;
        } else {
            //删除中间结点
            Node preNode = get(index - 1);
            preNode.next = preNode.next.next;
        }
        size--;
    }

七、移除末尾节点,并返回对应数据

    public T remove() {
        if (size == 1) {
            T data = head.data;
            head = null;
            tail = head;
            size--;
            return data;
        } else {
            Node preNode = get(size - 2);
            T data = tail.data;
            preNode.next = null;
            tail = preNode;
            size--;
            return data;
        }
    }

八、根据节点的值删除对应的节点

    public boolean deleteByData(T data) {
        boolean flag = false;
        if (size == 0) {
            return flag;
        } else {
            Node curNode = head;
            //元素位于第一个结点
            if (curNode.data == data) {
                head = curNode.next;
                flag = true;
                //当前列表只有一个结点
                if (this.size == 1) {
                    tail = head;
                }
                size--;
            } else {
                while (curNode != null) {
                    Node nextNode = curNode.next;
                    if (nextNode != null && nextNode.data == data) {
                        //删除元素为尾结点
                        if (nextNode.next == null) {
                            tail = curNode;
                            curNode.next = null;
                        } else {
                            //删除结点为中间结点
                            curNode.next = curNode.next.next;
                        }
                        flag = true;
                        size--;
                        break;
                    }
                    curNode = curNode.next;
                }
            }

        }
        return flag;
    }

九、打印输出链表中的值

    public void printLinkList() {
        if (size == 0) {
            System.out.println("链表长度为空");
        } else {
            Node temp = head;
            System.out.print("目前的列表,头结点:" + head.data + ",尾结点:" + tail.data + ",整体:");
            while (temp != null) {
                System.out.print(temp.data + ",");
                temp = temp.next;
            }
            System.out.println();
        }
    }

十、整体代码

public class LinkList<T> {

    //定义节点
    private class Node {
        //数据域
        T data;
        //指针域
        Node next;

        public Node(T data, Node next) {
            this.data = data;
            this.next = next;
        }

        public Node(T data) {
            this.data = data;
        }

        @Override
        public String toString() {
            return "Node{" +
                    "data=" + data +
                    ", next=" + next +
                    '}';
        }
    }

    private Node head;
    private Node tail;
    private int size;

    public LinkList() {
        this.head = new Node(null, null);
        this.size = 0;
    }

    public Node get(int index) {
        if (index < 0 || index >= size) {
            return null;
        } else {
            Node temp = this.head;
            //从头结点开始遍历至index位置
            for (int i = 0; i < index; i++) {
                temp = temp.next;
            }
            return temp;
        }
    }

    public void add(T data) {
        Node newNode = new Node(data);
        if (size == 0) {
            head = newNode;
            tail = head;
        } else {
            tail.next = newNode;
            tail = newNode;
        }
        size++;
    }

    public void insert(int index, T data) {
        if (index < 0 || index > size) {
            throw new RuntimeException("插入超出范围");
        }
        Node newNode = new Node(data);
        //头插
        if (index == 0) {
            if (this.size > 0) {
                newNode.next = head;
            }
            head = newNode;
        }
        //尾插
        else if (index == size) {
            tail.next = newNode;
            tail = newNode;
        } else {
            //获取要插入位置的前一个节点
            Node preNode = get(index - 1);
            //将要当前节点的指针指向前一个节点的下一个节点
            newNode.next = preNode.next;
            //将前一个节点的指针指向当前节点
            preNode.next = newNode;
        }
        size++;
        if (size == 1) {
            tail = head;
        }
    }

    public void del(int index) {
        if (index < 0 || index >= size) {
            throw new RuntimeException("删除超出范围");
        }
        if (index == 0) {
            head = head.next;
        } else if (index == size - 1) {
            Node preNode = get(size - 1);
            tail = preNode;
            preNode.next = null;
        } else {
            //删除中间结点
            Node preNode = get(index - 1);
            preNode.next = preNode.next.next;
        }
        size--;
    }

    //移除末尾元素,并返回对应数据
    public T remove() {
        if (size == 1) {
            T data = head.data;
            head = null;
            tail = head;
            size--;
            return data;
        } else {
            Node preNode = get(size - 2);
            T data = tail.data;
            preNode.next = null;
            tail = preNode;
            size--;
            return data;
        }
    }

    //删除特定元素的第一个位置
    public boolean deleteByData(T data) {
        boolean flag = false;
        if (this.size == 0) {
            return flag;
        } else {
            Node curNode = this.head;
            //元素位于第一个结点
            if (curNode.data == data) {
                head = curNode.next;
                flag = true;
                //当前列表只有一个结点
                if (this.size == 1) {
                    tail = head;
                }
                this.size--;
            } else {
                while (curNode != null) {
                    Node nextNode = curNode.next;
                    if (nextNode != null && nextNode.data == data) {
                        //删除元素为尾结点
                        if (nextNode.next == null) {
                            this.tail = curNode;
                            curNode.next = null;
                        } else {
                            //删除结点为中间结点
                            curNode.next = curNode.next.next;
                        }
                        flag = true;
                        this.size--;
                        break;
                    }
                    curNode = curNode.next;
                }
            }

        }
        return flag;
    }

    public void printLinkList() {
        if (size == 0) {
            System.out.println("链表长度为空");
        } else {
            Node temp = head;
            System.out.print("目前的列表,头结点:" + head.data + ",尾结点:" + tail.data + ",整体:");
            while (temp != null) {
                System.out.print(temp.data + ",");
                temp = temp.next;
            }
            System.out.println();
        }
    }

}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

随遇而安ing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值