双向链表

/**
 * 双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。
 * 所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。
 * 这也就导致了在对链表数据进行删除和添加的时候要明确指定出节点的前驱节点和后继节点。
 * @author 雪瞳
 *
 */
public class DoubleLinkTest<T> {

    /**
     * 内部构造节点类 
     * @param <T>
     */
    
    private class Node<T> {
        private T data;
        private Node next; // 指向下一个节点的引用
        private Node prev; // 指向前一个节点的引用

        public Node(T data) {
            this.data = data;
        }
    }

    private Node<T> head; // 模拟头结点
    private Node<T> last; // 模拟尾部节点
    private Node<T> other; // 暂定一个临时节点,用作指针节点
    private int length;

    public void DoubleLinkTest() {
        this.head = new Node<T>(null);
        this.last = head;
        this.length = 0;
    }

    public void DoubleLinkTest(T data) {
        this.head = new Node<T>(data);
        this.last = head;
        this.length = 0;
    }

    /**
     * 链表是否为空
     * @return
     */
    public boolean isEmpty() {
        return length == 0;
    }

    /**
     * 普通添加,往链表尾部添加
     * 
     * @param data
     */
    public void add(T data) {
        // 链表为空,新创建一个链表
        if (isEmpty()) { 
            head = new Node<T>(data);
            last = head;
            length++;
        } else {
            other = new Node<T>(data);
            // 将新的节点与原来的尾部节点进行结构上的关联
            // 尾节点的下一节点是other
            // other的前一个节点是尾结点
            last.next = other;
            other.prev = last;
            // other将成为最后一个节点
            last = other; 
            length++;
        }
    }

    /**
     * 在指定的数据后面添加数据
     * 
     * @param data 指定数据
     * @param insertData    添加的数据
     */
    public void addAfter(T data, T insertData) {
        // 设定指针节点是从头部节点开始遍历
        other = head;
        while (other != null) { 
            // 判断当前节点的数据是否是指定的数据
            if (other.data.equals(data)) {
                Node<T> insert = new Node<T>(insertData);
                // 对新插入的数据进行一个指向的定义
                // 由于是在指定数据之后插入 则节点的顺序是 other insert other.next 
                insert.prev = other;
                insert.next = other.next;
                other.next = insert;
                
                // 判断是不是在尾部插入
                // other的下一个节点是否为空 若为空则指定尾结点是insert
                if (insert.next == null) {
                    last = insert;
                }
                length++;
            }
            other = other.next;
        }
    }

    /**
     * 删除,删除指定的数据
     * 
     * @param data
     */
    public void remove(T data) {
        other = head;
        while (other != null) {
            if (other.data.equals(data)) {
                //当前节点other即为要删除的节点 则节点顺序为 other.prev<-->other.next
                other.prev.next = other.next;
                length--;
            }
            other = other.next;
        }

    }

    /**
     * 测试打印数据
     */
    public void printList() {
        other = head;
    /*    for (int i = 0; i < length; i++) {
            System.out.print(other.data + "\t");
            other = other.next;
        }*/
        while(other != null) {
            System.out.print(other.data+"\t");
            other = other.next;
        }
        System.out.println();
    }

    public static void main(String[] args) {

        DoubleLinkTest<Integer> testLink = new DoubleLinkTest<Integer>();
        //录入初始数据
        testLink.add(1);
        testLink.add(2);
        testLink.add(3);
        testLink.add(5);
        testLink.add(6);
        testLink.add(7);
        
        System.out.println("初始添数据为:");
        testLink.printList();

        System.out.println("在3后面添加一个数据");
        testLink.addAfter(3, 99);
        testLink.printList();

        System.out.println("移除一个指定的数据,数据为刚才添加的99");
        testLink.remove(99);
        testLink.printList();
    }

}

 双向链表

 

上一篇:docker的一些基本命令


下一篇:ElasticSearch简介