数据结构----链表

手写部分链表的代码

package com.ds.d230626;

import java.util.Arrays;

/**
 * 链表
 * @param <E>
 */
public class Test<E> implements Cloneable {
    /**
     * 链表长度
     */
    transient int size = 0;
    /**
     * 头节点
     */
    Node<E> first;
    /**
     * 尾节点
     */
    Node<E> last;

    private static class Node<E> {
        E element;
        Node<E> prev;
        Node<E> next;
        public Node(Node<E> prev, E element, Node<E> next) {
            this.prev = prev;
            this.element = element;
            this.next = next;
        }
    }

    /**
     * 头插
     * @param e 节点值
     */
    void linkFirst(E e) {
        // 获取头结点数据
        Node<E> f = first;
        // 获取新的节点数据,新节点的 next 指向头节点
        Node<E> node = new Node<>(null, e, first);
        first = node;
        if (f == null) {
            // 头结点是 null 值,新节点也就是尾节点
            last = node;
        } else {
            // 头结点不是 null 值,将头结点的 prev 指向新节点的
            f.prev = node;
        }
        size++;
    }

    /**
     * 尾插
     * @param e 节点值
     */
    void linkLast(E e) {
        Node<E> l = last;
        Node<E> node = new Node<>(last, e, null);
        last = node;
        if (l == null) {
            first = node;
        } else {
            l.next = node;
        }
        size++;
    }

    /**
     * 在某个节点前插入
     * @param e 要插入的值
     * @param node 节点
     */
    void linkBefore(E e, Node<E> node) {
        // node 节点的上一个节点
        Node<E> prevNode = node.prev;
        // 要插入的节点,因为是要出插入在 node 节点前,所以它的 prev 就是 node 节点的 prev, 它的 next 就是 node 节点
        Node<E> eNode = new Node<>(prevNode, e, node);
        if (prevNode == null) {
            // node 节点的 prev 指向为 null 时, eNode 节点就是头节点
            first = eNode;
        } else {
            // node 节点的 prev 指向不为 null 时,prevNode 的 next 指向 eNode 节点
            prevNode.next = eNode;
        }
        size++;
    }

    /**
     * 按顺序添加元素
     * @param e 元素值
     */
    public void add(E e) {
        linkLast(e);
    }

    /**
     * 在索引index处添加元素值
     * @param index 索引值
     * @param e 元素值
     */
    public void add(int index, E e) {
        checkPositionIndex(index);
        if (index == size) {
            linkLast(e);
        } else {
            linkBefore(e, getNodeByIndex(index));
        }
    }

    /**
     * 删链操作
     * @param node
     */
    void unLink(Node<E> node) {
        // 节点前指向节点
        Node<E> prevNode = node.prev;
        // 节点后指向节点
        Node<E> nextNode = node.next;
        if (prevNode == null) {
            // prevNode 为空,由于要删除 node 节点,所以 nextNode 节点就可以作为 first 节点
            first = nextNode;
        } else {
            // prevNode 为空,由于要删除 node 节点,所以 prevNode.next 就要指向 nextNode
            prevNode.next = nextNode;
            // 删除 node.prev 节点的关系
            node.prev = null;
        }

        if (nextNode == null) {
            // nextNode 为空,由于要删除 node 节点,所以 prevNode 节点就可以作为 last 节点
            last = prevNode;
        } else {
            // nextNode 为空,由于要删除 node 节点,所以 nextNode.prev 节点就要指向 prevNode
            nextNode.prev = prevNode;
            // 删除 node.next 节点的关系
            node.next = null;
        }
        size--;
    }

    /**
     * 删除元素
     * @param o 元素值
     */
    boolean remove(Object o) {
        if (o == null) {
            // 传入对象为 null 值情况
            for (Node<E> node = first; node != null; node = node.next) {
                // 遍历,查询 null 的节点值
                if (node.element == null) {
                    // 拆链操作
                    unLink(node);
                    return true;
                }
            }
        } else {
            for (Node<E> node = first; node != null; node = node.next) {
                // 遍历,对比节点值是否一致
                if (node.element.equals(o)) {
                    // 拆链操作
                    unLink(node);
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 根据索引获取当前节点
     * @param index 索引值
     * @return Node
     */
    Node<E> getNodeByIndex(int index) {
        // >> 右移操作,size >> 1 相当于 size 除以 2 取整
        if (index < (size >> 1)) {
            // 由于 index 在链表的前半部分,所以循环从 first 头节点开始
            Node<E> node = first;
            for (int i = 0; i < index; i++) {
                // node 下一个节点
                node = node.next;
            }
            return node;
        } else {
            // 由于 index 在链表的前半部分,所以循环从 last 尾节点开始
            Node<E> node = last;
            for (int i = (size - 1); i > index; i--) {
                // node 上一个节点
                node = node.prev;
            }
            return node;
        }
    }

    /**
     * 根据索引获取当前节点的值
     * @param index 索引值
     * @return E
     */
    public E get(int index) {
        checkElementIndexOut(index);
        return getNodeByIndex(index).element;
    }

    /**
     * 替换索引处的值
     * @param index 索引值
     * @param e 要替换的值
     */
    public void set(int index, E e) {
        checkElementIndexOut(index);
        // 获取索引处的节点
        Node<E> indexNode = getNodeByIndex(index);
        indexNode.element = e;
    }

    /**
     * 获取元素出现的第一个位置的索引值
     * @param o 元素值
     * @return int
     */
    public int indexOf(Object o) {
        int index = 0;
        if (o == null) {
            // 因为是要找最初出现的位置,所以从 first 头节点开始遍历;每一次循环结束 node 为下一个节点 node.next
            for (Node<E> node = first; node != null; node = node.next) {
                if (node.element == null) {
                    // 找到直接返回
                    return index;
                }
                // 未找到,索引值自增
                index++;
            }
        } else {
            // 因为是要找最初出现的位置,所以从 first 头节点开始遍历;每一次循环结束 node 为下一个节点 node.next
            for (Node<E> node = first; node != null; node = node.next) {
                if (node.element.equals(o)) {
                    // 找到直接返回
                    return index;
                }
                // 未找到,索引值自增
                index++;
            }
        }
        // 表是不存在这个值
        return -1;
    }

    /**
     * 获取元素出现的最后一个位置的索引值
     * @param o 元素值
     * @return int
     */
    public int lastIndexOf(Object o) {
        int index = size - 1;
        if (o == null) {
            // 因为是要找最初出现的位置,所以从 last 尾节点开始遍历;每一次循环结束 node 为下一个节点 node.next
            for (Node<E> node = last; node != null; node = node.prev) {
                if (node.element == null) {
                    // 找到直接返回
                    return index;
                }
                // 未找到,索引值自减
                index--;
            }
        } else {
            // 因为是要找最初出现的位置,所以从 last 尾节点开始遍历;每一次循环结束 node 为下一个节点 node.next
            for (Node<E> node = last; node != null; node = node.prev) {
                if (node.element.equals(o)) {
                    // 找到直接返回
                    return index;
                }
                // 未找到,索引值自减
                index--;
            }
        }
        // 表是不存在这个值
        return -1;
    }

    /**
     * 校验索引是否越界
     * @param index 索引值
     */
    private void checkElementIndexOut(int index) {
        if (!isElementIndex(index)) {
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
        }
    }

    /**
     * 校验索引是否越界
     * @param index 索引值
     */
    private boolean isElementIndex(int index) {
        return index >= 0 && index < size;
    }

    /**
     * 校验索引值是否在范围内
     * @param index 索引值
     */
    private void checkPositionIndex(int index) {
        if (!isPositionIndex(index)) {
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
        }
    }

    /**
     * 校验索引是否越界
     * @param index 索引值
     */
    private boolean isPositionIndex(int index) {
        return index >= 0 && index <= size;
    }

    /**
     * 异常提示信息
     * @param index 索引值
     */
    private String outOfBoundsMsg(int index) {
        return "Size:" + size + "; Index:" + index;
    }

    /**
     * 链表转换成数组
     * @return Object[]
     */
    public Object[] toArray() {
        Object[] result = new Object[size];
        int index = 0;
        for (Node<E> node = first; node != null; node = node.next) {
            result[index] = node.element;
            index++;
        }
        return result;
    }

    /**
     * 链表转换成对应数据类型的数组
     * @return T[]
     * @param <T> 泛型
     */
    public <T> T[] toArrayT(T[] arr) {
        if (arr.length < size) {
            // 复制一个 size 大小的数组
            arr = Arrays.copyOf(arr, size);
        }
        int index = 0;
        for (Node<E> node = first; node != null; node = node.next) {
            // 把链表中的数据存储到数组中
            arr[index++] = (T) node.element;
        }
        return arr;
    }

    /**
     * 深拷贝一个链表
     * @return Test
     */
    public Test<E> clone() {
        // 获取一个浅拷贝对象
        Test<E> clone = superClone();
        // 进行深拷贝
        clone.first = null;
        clone.last = null;
        clone.size = 0;
        for (Node<E> node = first; node != null ; node = node.next) {
            // 进行拷贝
            clone.add(node.element);
        }
        return clone;
    }

    /**
     * 获取一个浅拷贝对象
     * @return Test
     */
    private Test<E> superClone() {
        try {
            return (Test<E>) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new InternalError(e);
        }
    }


    public static void main(String[] args) {
        Test<Integer> t = new Test<>();
        t.linkFirst(3);
        t.linkFirst(5);
        t.linkFirst(6);
        t.linkFirst(1);
        t.linkFirst(11);
        t.linkLast(11);

        System.out.println(Arrays.toString(t.toArray()));

        Test<Integer> clone = t.clone();
        System.out.println(Arrays.toString(clone.toArray()));
        System.out.println(t == clone);
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值