Java实现双向链表

LinkedList类的实现

这里提供双向链表的实现,为避免与Java API冲突,取名为MyLinkedList。

LinkedList类的属性

public class MyLinkedList<AnyType> implements Iterable<AnyType> {
    private int theSize = 0;//链表的大小
    private int modCount = 0;//链表修改的次数
    private Node<AnyType> HeadNode;
    private Node<AnyType> LastNode;
}    

该类有四个属性,包括theSize,modCount,HeadNode,LastNode。其中modCount是对链表进行修改的次数,记录modCount的原因后面会说明。HeadNode和LastNode分别为头节点和尾节点,他们本身不存储数据,用于标记链表的头部和末尾。下面就其部分方法进行解释及类。

Node类

private static class Node<AnyType> {
    public AnyType data; //存储的数据
    public Node<AnyType> prevNode; //指向上一个节点
    public Node<AnyType> nextNode; //指向下一个节点
    public Node(AnyType data, Node<AnyType> prevNode, Node<AnyType> nextNode){
        this.data = data;
        this.nextNode = nextNode;
        this.prevNode = prevNode;
    }
}

Node类用于表示节点。其包含3个属性data,prevNode,nextNode以及一个构造器。

doClear方法

private void doClear() {
    HeadNode = new Node<AnyType>(null, null, null);
    LastNode = new Node<AnyType>(null, HeadNode, null);
    HeadNode.nextNode = LastNode;

    theSize = 0;
    modCount ++;
}

该方法用于初始化链表。初始化的过程如下:

  1. 将尾节点的前指针指向头节点
  2. 将头节点的后指针指向尾节点
  3. 将链表大小置0

该方法用于构造器及清空链表方法clear中

public MyLinkedList() {
    doClear();
}

public void clear() {
    doClear();
}

getNode方法

private Node<AnyType> getNode(int idx, int lower, int upper) {
    Node<AnyType> node;
    //如果索引超过了链表的索引,则报错
    if (idx < lower || idx > upper)
        throw new IndexOutOfBoundsException();

    //如果数据在前半段则从头节点开始检索,如果在后半段则从尾向前检索
    if (idx < size() / 2) {
        node = HeadNode.nextNode;
        for (int i = 0; i < idx; i ++) {
            node = node.nextNode;
        }
    } else {
            node = LastNode;
            for (int i = size(); i > idx; i --) {
            node = node.prevNode;
        }
    }

    return node;
}

该方法用于获取指定位置的节点。包含3个形参:idx,lower,upper。其中lower和upper用于表示索引的范围,当索引超出范围时会抛出异常。

获取节点的过程:

  1. 判断索引位于链表的前半段还是后半段
  2. 位于前半段则从头节点开始向后遍历,位于后半段则从尾节点开始向前遍历

该方法可以用于获取指定节点数据、获取指定节点、删除指定位置节点等。

LinkedListIterator类

private class LinkedListIterator implements Iterator<AnyType> {
    private MyLinkedList.MyLinkedList.Node<AnyType> current = HeadNode.nextNode; //当前节点的下一个节点
    private int expectedModCount = modCount;//确保迭代器在使用时原表数据没有变动
    private boolean okToRemove = false;

    @Override
    public boolean hasNext() {
        return current != LastNode;
    }

    @Override
    public AnyType next() {
        //确保迭代器在使用时原表数据没有变动
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
        if (!hasNext())
            throw new NoSuchElementException();

        AnyType nextItem = current.data;
        current = current.nextNode;
        okToRemove = true; //确保能够使用Remove
        return nextItem;
    }

    public void remove() {
        //确保迭代器在使用时原表数据没有变动
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
        if (!okToRemove)
            throw new IllegalStateException();

        MyLinkedList.this.remove(current.prevNode);
        expectedModCount ++;
        okToRemove = false;
    }
}

该类用于创建LinkedList的迭代器。包含了3个属性:current、expectedModCount、okToRemove。c其中urrent表示当前节点的下一个节点。expectedModCount用于判断在使用迭代器的过程中,链表是否进行过修改。如果进行过修改,则迭代器失效。okToRemove保证迭代器能够使用remove方法,防止出现异常。

hasNext的实现原理是判断current是否为尾节点,如果为尾节点则说明当前节点位于链表的尾部。

全部代码

public class MyLinkedList<AnyType> implements Iterable<AnyType> {
    private int theSize = 0;//链表的大小
    private int modCount = 0;//链表修改的次数
    private Node<AnyType> HeadNode;
    private Node<AnyType> LastNode;

    public MyLinkedList() {
        doClear();
    }

    /**
     * @Author: pocean
     * @Description: 节点
     * @Date: 15:31 2021/9/25
     */
    private static class Node<AnyType> {
        public AnyType data; //存储的数据
        public Node<AnyType> prevNode; //指向上一个节点
        public Node<AnyType> nextNode; //指向下一个节点
        public Node(AnyType data, Node<AnyType> prevNode, Node<AnyType> nextNode){
            this.data = data;
            this.nextNode = nextNode;
            this.prevNode = prevNode;
        }
    }

    public void clear() {
        doClear();
    }

    public int size() {
        return theSize;
    }

    public boolean isEmpty() {
        return size() == 0;
    }

    /**
     * @Author: pocean
     * @Description: 初始化链表
     * @Date: 15:37 2021/9/25
     */
    private void doClear() {
        HeadNode = new Node<AnyType>(null, null, null);
        LastNode = new Node<AnyType>(null, HeadNode, null);
        HeadNode.nextNode = LastNode;

        theSize = 0;
        modCount ++;
    }

    /**
     * @Author: pocean
     * @Description: 添加数据至链表末尾
     * @Date: 15:55 2021/9/25
     */
    public void add(AnyType x) {
        add(size(), x);
    }

    /**
     * @Author: pocean
     * @Description: 添加数据至指定位置
     * @Date: 15:56 2021/9/25
     */
    public void add(int idx, AnyType data) {
        addBefore(getNode(idx,0,size()), data);
    }

    /**
     * @Author: pocean
     * @Description: 获取指定位置节点的数据
     * @Date: 15:58 2021/9/25
     */
    public AnyType getData(int idx) {
        return getNode(idx).data;
    }

    /**
     * @Author: pocean
     * @Description: 设置指定位置的节点数据
     * @Date: 16:00 2021/9/25
     */
    public void set(int idx, AnyType newVal) {
        Node<AnyType> p = getNode(idx);
        p.data = newVal;
    }

    /**
     * @Author: pocean
     * @Description: 添加至指定节点的前端
     * @Date: 15:40 2021/9/25
     */
    private void addBefore(Node<AnyType> p, AnyType x) {
        //将数据存入新节点,新节点的前指针指向指定节点的前一个节点,后指针指向指定节点
        Node<AnyType> newNode = new Node<AnyType>(x, p.prevNode, p);
        //将指定指针的前一个节点指向新节点
        p.prevNode.nextNode = newNode;
        //将指定指针的前指针指向新节点
        p.prevNode = newNode;
        //添加完毕
        theSize ++;
        modCount ++;
    }

    /**
     * @Author: pocean
     * @Description: 删除指定节点
     * @Date: 15:54 2021/9/25
     */
    private void remove(Node<AnyType> p) {
        //将该节点的后一个节点的前指针指向该节点的前一个节点
        p.nextNode.prevNode = p.prevNode;
        //将该节点的前一个节点的后指针指向该节点的后一个节点
        p.prevNode.nextNode = p.nextNode;
        //移除完毕
        theSize --;
        modCount ++;
    }

    /**
     * @Author: pocean
     * @Description: 获取指定位置的节点
     * @Date: 16:06 2021/9/25
     */
    private Node<AnyType> getNode(int idx) {
        return getNode(idx, 0, size() - 1);
    }

    /**
     * @Author: pocean
     * @Description: 获得指定位置的节点
     * @Date: 16:07 2021/9/25
     */
    private Node<AnyType> getNode(int idx, int lower, int upper) {
        Node<AnyType> node;
        //如果索引超过了链表的索引,则报错
        if (idx < lower || idx > upper)
            throw new IndexOutOfBoundsException();

        //如果数据在前半段则从头节点开始检索,如果在后半段则从尾向前检索
        if (idx < size() / 2) {
            node = HeadNode.nextNode;
            for (int i = 0; i < idx; i ++) {
                node = node.nextNode;
            }
        } else {
            node = LastNode;
            for (int i = size(); i > idx; i --) {
                node = node.prevNode;
            }
        }

        return node;
    }

    private class LinkedListIterator implements Iterator<AnyType> {
        private MyLinkedList.MyLinkedList.Node<AnyType> current = HeadNode.nextNode; //当前节点的下一个节点
        private int expectedModCount = modCount;//确保迭代器在使用时原表数据没有变动
        private boolean okToRemove = false;

        @Override
        public boolean hasNext() {
            return current != LastNode;
        }

        @Override
        public AnyType next() {
            //确保迭代器在使用时原表数据没有变动
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
            if (!hasNext())
                throw new NoSuchElementException();

            AnyType nextItem = current.data;
            current = current.nextNode;
            okToRemove = true; //确保能够使用Remove
            return nextItem;
        }

        public void remove() {
            //确保迭代器在使用时原表数据没有变动
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
            if (!okToRemove)
                throw new IllegalStateException();

            MyLinkedList.this.remove(current.prevNode);
            expectedModCount ++;
            okToRemove = false;
        }
    }

    @Override
    public Iterator<AnyType> iterator() {
        return new LinkedListIterator();
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值