链表,Java自定义链表的实现(单向,循环,双向)

1.链表
链表是由节点组成的。
节点是由数据域+引用域组成的。
节点与节点之间是通过引用域进行链接的。
这里写图片描述
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构,操作复杂。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn)和O(1)。
使用链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。链表最明显的好处就是,常规数组排列关联项目的方式可能不同于这些数据项目在记忆体或磁盘上顺序,数据的存取往往要在不同的排列顺序中转换。链表允许插入和移除表上任意位置上的节点,但是不允许随机存取。链表有很多种不同的类型:单向链表,双向链表以及循环链表。

2.链表实现

难点:找到当前节点,和下一个节点,上一个节点,改变其引用域
具体看代码

1.定义节点类

public class Node {
    private Object data;
    private Node next;
    private Node befor;

    public Node() {

    }
    public Node(Object data) {
        super();
        this.data = data;
    }
    public Node getBefor() {
        return befor;
    }
    public void setBefor(Node befor) {
        this.befor = befor;
    }
    public Object getData() {
        return data;
    }
    public void setData(Object data) {
        this.data = data;
    }
    public Node getNext() {
        return next;
    }
    public void setNext(Node next) {
        this.next = next;
    }
}

2.定义链表类

public class MyLinkedList<E> {
    private Node root = new Node();// 空节点
    private Node next;// 下一个节点
    private Node last;// 始终表示最后一个节点
    private int size;

    public int size() {
        return size;
    }

    /**
     * 向链表添加节点的方法
     */
    public void add(E e) {
        next = new Node(e);
        if (size == 0) {// 如果是第一个节点
            root.setNext(next);// 添加到空节点后面
            last = next;// 更新最后一个节点
            size++;
        } else {
            last.setNext(next);// 添加到最后一个节点后面
            last = next;// 更新最后一个节点
            size++;
        }
    }

    /**
     * get节点元素的方法
     */
    public Object get(int index) {
        checkIndex(index);// 检查index
        Node node = root.getNext();
        for (int i = 0; i < index; i++) {// 找到下标为index的节点
            node = node.getNext();
        }
        return node.getData();

    }

    /**
     * set节点元素的方法
     */
    public void set(int index, E e) {
        checkIndex(index);// 检查index
        Node node = root.getNext();
        for (int i = 0; i < index; i++) {// 找到下标为index的节点
            node = node.getNext();
        }
        node.setData(e);

    }

    /**
     * remove节点的方法
     */
    public void remove(int index) {
        checkIndex(index);// 检查index
        Node node = root.getNext();
        if (index != 0) {//如果不是第一个节点
            for (int i = 0; i < index; i++) {// 找到下标为index的节点
                node = node.getNext();
            }
            // 找到下标为index-1的节点,即前一个节点
            Node node1 = root.getNext();
            for (int i = 0; i < index - 1; i++) {
                node1 = node1.getNext();
            }

            if (index != size - 1) {// 如果不是最后一个节点
                Node node2 = node.getNext();// 下标index的下一个节点
                node1.setNext(null);// 断开前一个节点和index节点
                node1.setNext(node2);// 将前一个节点指向后一个节点
            } else {// 是最后一个节点
                node1.setNext(null);// 断开前一个节点和index节点
            }
            node.setData(null);// 删除节点存贮的内容
            node.setNext(null);// 删除index节点指向
        } else {//移除第一个节点
            Node node4 = root.getNext();
            Node node5 = node4.getNext();
            root.setNext(null);
            root.setNext(node5);
            node4.setNext(null);

        }
        size--;
    }

    /**
     * 插入节点的方法
     */
    public void insert(int index, E e) {
        checkIndex(index);// 检查index
        // 找到下标为index的节点
        Node node = root.getNext();
        for (int i = 0; i < index; i++) {
            node = node.getNext();

        }
        Node node1 = new Node(e);
        if (index == 0) {// 如果要插入在最前面
            root.setNext(null);// 断开空节点和第一个节点
            root.setNext(node1);// 空节点指向新节点
            node1.setNext(node);// 新节点指向原第一个节点

        } else {
            // 找到下标为index节点的前一个节点
            Node node2 = root.getNext();
            for (int i = 0; i < index - 1; i++) {
                node2 = node2.getNext();
            }
            node2.setNext(null);// 断开前一个节点
            node2.setNext(node1);
            node1.setNext(node);
        }
        size++;
    }

    /**
     * 反转
     */

    public void back() {
        int num = size - 1;
        Node node = root.getNext();// 得到下标为num的点
        for (int i = 0; i < num; i++) {
            node = node.getNext();
        }
        last = node;// 更新last
        if (num > 0) {

            for (int j = 0; j < num; j++) {
                Node node1 = root.getNext();// 找到下标为num-j-1的点
                for (int i = 0; i < num - j - 1; i++) {
                    node1 = node1.getNext();
                }

                node1.setNext(null);// 该节点的引用域为空
                last.setNext(node1);// 最后一个几点指向该节点
                last = node1;// 更新最后一个节点
            }
            num--;
        }
        root.setNext(null);// 断开根节点与原第一个节点
        root.setNext(node);// 根节点指向原最后一个节点

    }

    /**
     * 添加循环链表
     */
    public void addfor(E e) {
        next = new Node(e);
        if (size == 0) {// 如果是第一个节点
            root.setNext(next);// 添加到空节点后面
            last = next;// 更新最后一个节点
            size++;
        } else {
            last.setNext(next);// 添加到最后一个节点后面
            last = next;// 更新最后一个节点
            last.setNext(null);
            last.setNext(root.getNext());// 最后一个节点指向第一个节点
            size++;
        }
    }

    /**
     * 添加双向链表
     */
    public void duladd(E e) {
        next = new Node(e);
        if (size == 0) {// 如果是第一个节点
            root.setNext(next);// 添加到空节点后面
            last = next;// 更新最后一个节点
            size++;
        } else {

            last.setNext(next);// 添加到最后一个节点后面
            next.setBefor(last);// next指向前一个节点
            last = next;// 更新最后一个节点
            size++;
        }
    }

    /**
     * 检查下标Index是否合法
     */
    private void checkIndex(int index) {
        if (index < 0 || index > size) {// 不合法报错
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
        }
    }

    private String outOfBoundsMsg(int index) {
        return "Index: " + index + ", Size: " + size;
    }
}

3.定义检查链表是否正确的类:

public class Manage {

    public static void main(String[] args) {
        MyLinkedList<Comparable> list = new MyLinkedList();//创建单向列表对象
        Random ran = new Random();
        int num = ran.nextInt(5)+5;
        System.out.println("添加的个数为"+num);
        System.out.println("---添加---");
        for(int i=0;i<num;i++){
            list.add(i);
            System.out.print("  "+list.get(i));
        }
        System.out.println();
        System.out.println("添加后链表的Size为:"+list.size());
        System.out.println();
        //设置
        list.set(1, "5");
        for(int i=0;i<num;i++){
            System.out.print("  "+list.get(i));
        }
        System.out.println();
        System.out.println("移除最后一个");
        //移除
        list.remove(num-1);
        for(int i=0;i<list.size();i++){
            System.out.print("  "+list.get(i));
        }
        System.out.println();
        System.out.println("移除链表的Size为:"+list.size());
        System.out.println();
        //插入
        System.out.println("---插入---");
        list.insert(num-2, "999");
        for(int i=0;i<list.size();i++){
            System.out.print("  "+list.get(i));
        }
        System.out.println();
        System.out.println("插入链表的Size为:"+list.size());
        //反转
        list.back();
        System.out.println();
        System.out.println("---反转---");
        for(int i=0;i<list.size();i++){
            System.out.print("  "+list.get(i));
        }
        System.out.println();
        System.out.println("反转链表的Size为:"+list.size());
        System.out.println("---------------------------------");


        //添加循环链表
        MyLinkedList list1 = new MyLinkedList();
        for(int i=0;i<num;i++){
            list1.addfor(i);
        }

        for(int i=0;i<list1.size();i++){
            System.out.print("  "+list1.get(i));
        }
        System.out.println();

        list1.insert(0,"23");
        for(int i=0;i<list1.size();i++){
            System.out.print("  "+list1.get(i));
        }
        System.out.println();


    }

}

输出结果:
这里写图片描述

猜你喜欢

转载自blog.csdn.net/lzq1326253299/article/details/82151350