从零开始复习数据结构--双向链表

参考LinkedLits源码

链表中添加节点到B节点之前

如果B节点为头节点,需要将first指针指向B

1.构造节点X

Node<E> X= new Node<>(A, e, B);

 

2.断开AB之间的链,重新指向X

A.next = X

B.prev = X

 

    private void linkBefore(E e, Node succ) {
        Node pred = succ.prev;
        Node newNode = new Node<>(pred, e, succ);
        succ.prev = newNode;
        if (pred == null) {
            first = newNode;
        } else {
            pred.next = newNode;
        }
        size++;
    }

 

 

移除节点B

如果B为尾节点或头节点,直接偏移对应指针

将A.next指向C,将C.prev指向A

A.next = C

C.prev = A

    private E unLink(Node node) {
        E element = node.element;
        Node prev = node.prev;
        Node next = node.next;
        //头节点处理
        if (prev == null) {
            first = next;
        } else {
            prev.next = node.next;
            node.prev = null;
        }

        //尾节点处理
        if (next == null) {
            last = prev;
        } else {
            next.prev = prev;
            node.next = null;
        }

        node.element = null;
        size--;
        return element;
    }

 

 

 

完整代码

public class MyLinkedList {
    Node first;
    Node last;
    int size = 0;

    public MyLinkedList() {
    }

    /**
     * 连接到链表首部
     * 如果链表为空(头指针为空),则将链表头指针和尾指针指向该节点
     * 否则将元素直接连接到链表首部
     *
     * @param e
     */
    private void linkFirst(E e) {
        Node f = first;
        Node newNode = new Node<>(null, e, f);
        first = newNode;
        if (f == null) {
            last = newNode;
        } else {
            f.prev = newNode;
        }
        size++;
    }

    /**
     * 连接到链表尾部
     * 如果链表为空(尾指针为空),则将头指针和尾指针指向该节点
     * 否则将元素直接连接到尾部
     *
     * @param e
     */
    private void linkLast(E e) {
        Node l = last;
        Node newNode = new Node<>(last, e, null);
        last = newNode;
        if (l == null) {
            first = newNode;
        } else {
            l.next = newNode;
        }
        size++;
    }

    /**
     * 连接到节点的前一个元素
     *
     * @param e
     * @param succ
     */

    private void linkBefore(E e, Node succ) {
        Node pred = succ.prev;
        Node newNode = new Node<>(pred, e, succ);
        succ.prev = newNode;
        if (pred == null) {
            first = newNode;
        } else {
            pred.next = newNode;
        }
        size++;
    }

    /**
     * 删除节点
     * 考虑节点为头指针和尾指针的情况
     *
     * @param node
     * @return
     */
    private E unLink(Node node) {
        E element = node.element;
        Node prev = node.prev;
        Node next = node.next;
        //头节点处理
        if (prev == null) {
            first = next;
        } else {
            prev.next = node.next;
            node.prev = null;
        }

        //尾节点处理
        if (next == null) {
            last = prev;
        } else {
            next.prev = prev;
            node.next = null;
        }

        node.element = null;
        size--;
        return element;
    }

    /**
     * 检查元素是否越界
     *
     * @param index
     * @throws Exception
     */
    private void checkIndex(int index) throws Exception {
        if (index < 0 || index > size) {
            throw new Exception("元素越界");
        }
    }

    /**
     * 根据位置添加节点
     *
     * @param index
     * @param e
     */
    public void add(int index, E e) {
        try {
            checkIndex(index);
            if (index == 0) linkFirst(e);
            else if (index == 1) linkLast(e);
            else linkBefore(e, searchNode(index));
        } catch (Exception e1) {
            e1.printStackTrace();
        }
    }

    /**
     * 将节点直接添加到尾部
     *
     * @param e
     */
    public void add(E e) {
        linkLast(e);
    }

    /**
     * 直接移除链表尾部元素
     * @return
     */

    public E remove(){
        return unLink(last);
    }
    /**
     * 移除指定位置的元素
     */
    public E remove(int index){
        E element=null;
        try {
            Node node=searchNode(index);
            element=node.element;
            unLink(node);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return element;
    }

    /**
     * 根据位置查找节点
     * 如果位置位于前半部分,从首部开始遍历
     * 否则从尾部开始遍历
     *
     * @param index
     * @return
     */
    private Node searchNode(int index) throws Exception {
        checkIndex(index);
        if (index < (size >> 1)) {
            Node indexNode = first;
            for (int i = 0; i < index; i++) {
                indexNode = indexNode.next;
            }
            return indexNode;
        } else {
            Node indexNode = last;
            for (int i = size - 1; i > index; i--) {
                indexNode = indexNode.prev;
            }
            return indexNode;
        }
    }

    /**
     * 遍历元素并输出
     *
     * @return
     */
    public void ergodic() {
        Node node = first;
        for (int i = 0; i < size; i++) {
            System.out.println(node.element);
            node = node.next;
        }
    }

    class Node {
        Node prev;
        Node next;
        E element;

        public Node(Node prev, E element, Node next) {
            this.prev = prev;
            this.next = next;
            this.element = element;
        }
    }

    public static void main(String args[]) {
        MyLinkedList linkedList = new MyLinkedList();
        for (int i = 0; i < 10; i++) {
            linkedList.add("node" + i);
        }
        linkedList.ergodic();
        System.out.println("------------------------");
        for (int i=0;i<5;i++){
            linkedList.remove();
        }
        linkedList.remove(3);
        linkedList.ergodic();
    }
}

 

 

你可能感兴趣的:(从零开始复习数据结构--双向链表)