双向链线性表-java语言版

301 阅读2分钟

双向链表也叫双向表,是链表的一种,它由多个结点组成,每个结点都由一个数据域和两个指针域组成,数据域用 来存储数据,其中一个指针域用来指向其后继结点,另一个指针域用来指向前驱结点。链表的头结点的数据域不存 储数据,指向前驱结点的指针域值为null,指向后继结点的指针域指向第一个真正存储数据的结点。

双向链表原理图.png 按照面向对象的思想,我们需要设计一个类,来描述结点这个事物。由于结点是属于链表的,所以我们把结点类作 为链表类的一个内部类来实现

-- 结点API设计:

结点API设计.png

-- 双向链API设计:

双向链API设计.png

-- 代码:

/**
 * 双向链,线性表
 */
public class TowWayLinkList<T> implements Iterable{
    // 首结点
    private Node head;
    // 最后一个结点
    private Node last;
    // 链表长度
    private int N;

    // 构造方法
    public TowWayLinkList() {
        head = new Node(null,null,null);
        last = null;
        N = 0;
    }

    // 清空链表
    public void clear() {
        last = null;
        head.pre = null;
        head.next = null;
        head.item = null;
        N = 0;
    }

    // 获取链表长度
    public int length() {
        return N;
    }

    // 判断链表是否为空
    public boolean isEmpty() {
        return N == 0;
    }

    // 插入元素t
    public void insert(T t) {
        if(last == null) {
            // 如果是第一次插入执行
            last = new Node(t,head,null);
            head.next = last;
        }else {
            // 不是第一次插入执行
            Node node = new Node(t,last,null);
            last.next = node;
            last = node;
        }
        // 长度+1
        N++;
    }

    // 向指定位置i处插入元素t
    public void insert(int i,T t) {
        // 检查插入位置是否合法
        if(i < 0 || i > N - 1) {
            throw new RuntimeException("位置不合法");
        }
        // 找到位置i的前一个结点
        Node pre = head;
        for(int index = 0;index <= i - 1;index++) {
            pre = pre.next;
        }
        // 当前结点
        Node curr = pre.next;
        // 构建新结点
        Node newNode = new Node(t,pre,curr);
        pre.next = newNode;
        curr.pre = newNode;
        // 长度+1
        N++;
    }

    // 获取指定位置i处的元素
    public T get(int i) {
        // 检查获取位置是否合法
        if(i < 0 || i > N - 1) {
            throw new RuntimeException("位置不合法");
        }
        // 寻找当前结点
        Node curr = head;
        for(int index = 0;index <= i;index++) {
            curr = curr.next;
        }
        return curr.item;
    }

    // 找到元素t第一次在链表中出现的位置
    public int indexOf(T t) {
        Node n = head;
        for(int i = 0;n.next != null;i++) {
            n = n.next;
            if(n.item.equals(t)) {
                return i;
            }
        }
        return -1;
    }

    // 删除位置i处的元素,并返回该元素
    public T remove(int i) {
        // 判断删除位置是否合法
        if(i < 0 || i > N - 1) {
            throw new RuntimeException("位置不合法");
        }
        // 寻找i位置的前一个元素
        Node pre = head;
        for (int index = 0;index <= i - 1;index++) {
            pre = pre.next;
        }
        // i位置处的元素
        Node curr = pre.next;
        // i置为处的下一个元素
        Node curr_next = curr.next;
        pre.next = curr_next;
        curr_next.pre = pre;
        // 长度-1
        N--;
        return curr.item;
    }
    // 获取第一个元素
    public T getFirst() {
        // 判断元素是否为空
        if(isEmpty()) {
            return null;
        }
        return head.next.item;
    }
    // 获取最后一个元素
    public T getLast() {
        if(isEmpty()) {
            return null;
        }
        return last.item;
    }

    // 结点类
    class Node {
        // 存储数据
        private T item;
        // 指向上一个结点
        private Node pre;
        // 指向下一个结点
        private Node next;
        // 构造方法
        public Node(T item,Node pre,Node next) {
            this.item = item;
            this.pre = pre;
            this.next = next;
        }
    }
    //==============================================================================
    // 实现for-each遍历的
    @Override
    public Iterator iterator() {
        return new TIterator();
    }

    class TIterator<T> implements Iterator {
        private Node n;

        // 构造方法
        public TIterator() {
            n = head;
        }
        // 是否还有下一个元素
        @Override
        public boolean hasNext() {
            return n.next != null;
        }
        // 获取下一个元素
        @Override
        public Object next() {
            n = n.next;
            return n.item;
        }
    }
}

-- 测试代码:

public class TowWayLinkListTest {
    public static void main(String[] args) throws Exception {
        TowWayLinkList<String> list = new TowWayLinkList<>();
        list.insert("乔峰");
        list.insert("虚竹");
        list.insert("段誉");
        list.insert(1, "鸠摩智");
        list.insert(3, "叶二娘");

        for (Object str : list) {
            System.out.println(str);
        }
        System.out.println("----------------------");
        String tow = list.get(2);
        System.out.println(tow);
        System.out.println("-------------------------");
        String remove = list.remove(3);
        System.out.println(remove);
        System.out.println(list.length());
        System.out.println("--------------------");
        System.out.println(list.getFirst());
        System.out.println(list.getLast());
    }
}

-- 运行效果图:

双向表运行效果.png

@ 以上内容属于个人笔记