数据结构 -- 链表 (Java)

JAVA中自带的的LinkedList, 是一个双向链表,而使用双向链表的好处就是操作速度相比于单向链表快捷,因此在手搓链表的时候我们也选择用双向链表尽可能的去模拟LinkedList同时理解链表。

一、效果展示

自己搓的:

官方的:

 如图:能够实现基本的增删改查,且与官方的大致相同

二、 代码展示

MyLinkList 类 

// 这是一个构造方法,用来创建一个空的链表
public MyLinkList() {
    this.fist = null;
    this.last = null;
}


// 这是一个方法,用来在链表的末尾添加一个元素
public boolean add(E e) {
    if (fist == null) {
        // 如果链表为空,就创建一个新的节点,把给定的元素作为数据,并把它赋值给first和last字段
        Node<E> newnode = new Node<>(e, null, null);
        last = newnode;
        fist = newnode;
    } else {
        // 如果链表不为空,就创建一个新的节点,把给定的元素作为数据,并把它插入到last节点的后面
        Node<E> newnode = new Node<>(e, last, null);
        last.setNext(newnode);
        last = newnode;

    }
    // 把链表的大小加一,并返回true表示添加成功
    this.size++;
    return true;
}

// 这是一个方法,用来在链表的指定位置插入一个元素
public void add(int index, E element) {
    // 定义一个当前节点的引用,初始指向first节点
    Node<E> current = fist;
    if (index == size) {
        // 如果索引等于链表的大小,就调用add方法在末尾添加元素
        add(element);
    } else if (index == 0) {
        // 如果索引等于0,就创建一个新的节点,并把它插入到first节点的前面
        Node<E> newnode = new Node<>(element, null, fist);
        fist.setPrev(newnode);
        fist = newnode;
    } else {
        // 如果索引在0和size之间,就遍历链表,找到对应位置的节点
        int i = 0;
        while (i++ != index) {
            current = current.getNext();
        }
        // 创建一个新的节点,并把它插入到当前节点的前面和后面节点之间
        Node<E> newnode = new Node<>(element, current.getPrev(), current);
        current.getPrev().setNext(newnode);
        current.setPrev(newnode);
    }
}

// 这是一个方法,用来从链表中删除一个元素
public boolean remove(E e) {
    // 定义一个计数器和当前节点的引用,初始指向first节点
    int i = 0;
    Node<E> current = fist;
    while (i++ != size - 1) {
        // 遍历链表,如果找到数据等于给定元素的节点,就删除它,并返回true表示删除成功
        if (current.getData() == e) {
            if (current.getPrev() != null) current.getPrev().setNext(current.getNext());
            else {
                System.out.println("报错");
            }
            return true;
        }
        // 否则继续遍历下一个节点
        current = (current.getNext());
    }
    // 如果遍历完毕没有找到匹配的节点,就把first和last都设为null,并把size设为0,并返回false表示删除失败
    fist = null;
    last = null;
    size--;
    return false;
}

// 这是一个方法,用来从链表中删除指定位置的元素,并返回被删除的元素
public Object remove(int index) {

    if (index == 0) {
        // 如果索引等于0,就保存first节点,并把first节点设为它的下一个节点,并断开原来first节点的连接
        Node<E> re = fist;
        Node<E> node = fist.getNext();
        fist.setNext(null);
        node.setPrev(null);
        fist = node;
        // 把链表的大小减一,并返回被删除的元素
        size--;
        return re.getData();
    } else {
        // 如果索引不等于0,就找到对应位置的节点,并把它从链表中移除
        Node<E> current = getN(index);
        current.getPrev().setNext(current.getNext());
        // 把链表的大小减一,并返回被删除的元素
        size--;
        return current.getData();
    }

}

// 这是一个私有方法,用来根据索引获取链表中的节点
private Node<E> getN(int index) {

    // 定义一个计数器和当前节点的引用,初始指向first节点
    int i = 0;
    Node<E> current = fist;
    while (i++ != index) {
        // 遍历链表,直到找到对应位置的节点
        current = current.getNext();
    }
    // 返回该节点
    return current;
}

// 这是一个方法,用来根据索引获取链表中的元素
public E get(int index) {

    // 调用getN方法获取对应位置的节点,并返回它的数据
    return getN(index).getData();
}

// 这是一个方法,用来获取链表中的第一个元素
public E getFirst() {
    // 返回first节点的数据
    return fist.getData();
}

// 这是一个方法,用来获取链表中的最后一个元素
public E getLast() {
    // 返回last节点的数据
    return last.getData();
}

// 这是一个方法,用来修改链表中指定位置的元素,并返回原来的元素
public E set(int index, E element) {
    // 调用getN方法获取对应位置的节点,并保存它的数据
    Node<E> current = getN(index);
    E e = current.getData();
    // 把给定的元素设为当前节点的数据,并返回原来的数据
    current.setData(element);
    return e;

}

// 这是一个方法,用来清空链表中的所有元素
public void clear() {
    // 定义一个计数器,并从last节点开始遍历链表
    int i = 0;
    while (i++ != size - 1) {
        // 保存last节点的前一个节点,并断开last节点的连接
        Node<E> rem = last.getPrev();
        last.setPrev(null);
        last.setNext(null);
        last = rem;
    }
    // 把last和first都设为null,并把size设为0
    last = null;
    fist = null;
    size = 0;
}

// 这是一个方法,用来获取链表中元素的个数
public int size() {
    // 返回size字段的值
    return size;
}

@Override
// 这是一个重写的方法,用来把链表转换为字符串形式
public String toString() {
    // 创建一个字符串连接器,用来拼接链表中的元素,使用逗号分隔,使用方括号包围
    StringJoiner stringJoiner = new StringJoiner(", ", "[", "]");
    // 定义一个当前节点的引用,初始指向first节点,并遍历链表
    Node<E> current = fist;
    for (int i = 0; i < size; i++) {
        // 把当前节点的数据添加到字符串连接器中,并继续遍历下一个节点
        stringJoiner.add((CharSequence) current.getData());
        current = current.getNext();
    }
    // 返回字符串连接器生成的字符串
    return stringJoiner.toString();
}

Node 类

public class Node<E> {
    private Node<E> prev;
    private Node<E> next;
    private E data;

    public Node(E data, Node<E> prev, Node<E> next) {
        this.data = data;
        this.prev = prev;
        this.next = next;
    }

    public Node<E> getPrev() {
        return prev;
    }

    public void setPrev(Node<E> prev) {
        this.prev = prev;
    }

    public Node<E> getNext() {
        return next;
    }

    public void setNext(Node<E> next) {
        this.next = next;
    }

    public E getData() {
        return data;
    }

    public void setData(E data) {
        this.data = data;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小户爱

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

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

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

打赏作者

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

抵扣说明:

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

余额充值