用链表实现线性表

在实现的时候我们先来说说什么是链表?

其实,链表就像是解密游戏一样,只有到达一个地点,才会有NPC给你下一个地点的地图,从而才能知道下个地点的位置
所以链表也是一样,对于一个链表,一个结点除了要保存结点自身的值以外,还需要保存下一个结点的地址.
image

这是一个简单链表的单个结点,val代表当前结点存储的值,next是一个引用,指向下一个结点
由于Java中不存在指针,所以结点通常为一个类,而next则是一个结点类实例的引用
image

可以看到,每一结点都保存了下一个节点的地址,所以,链表不要求每个结点中的地址空间连续
所以如何创建一个链表呢?那么下面我们就来实现

方法接口

定义一个方法接口

public interface ListMethods<T> {
    void clear();
    boolean isEmpty();
    int length();
    T get(int i);
    void insert(T t);
    void insert(int i, T t);
    T remove(int i);
    int indexOf(T t);
}

创建链表类

public class LinkList<T> {
    private Node head; // 头节点
    private int N; // 链表元素统计数

    // 在类中创建一个私有类
    private class Node {
        T item; // 用来存储数据元素
        Node next; // 定一个Node对象来指向下一个类的地址

        public Node(T item, Node next) {
            this.item = item;
            this.next = next;
        }
    }

    public LinkList() {
        this.head = new Node(null, null);
        this.N = 0;
    }
}

清空链表

    public void clear() {
        head.next = null;
        this.N = 0;
    }

判断链表是否为空

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

获取链表长度

    public int length() {
        return N;
    }

获取指定位置的元素

    public T get(int i) {
        if(head.next == null) {
            return null;
        }
        Node n = head.next;
        for (int index = 0; index < i; index++) {
            n = n.next;
        }
        return n.item;
    }

向线性表中添加元素t

    public void insert(T t) {
        Node n = head;  // 把头节点复制给一个新元素
        while (n.next != null) {
            n = n.next;
        }
        n.next = new Node(t, null);
        N++;
    }

在i元素处插入元素t

    public void insert(int i, T t) {
        Node n = head;
        for (int index = 0; index < i; index++) {
            n = n.next;
        }
        n.next = new Node(t, n.next);
        N++;
    }

删除线性表中下标为i的元素

    public T remove(int i) {
        Node n = head;
        for (int index = 0; index < i; index++) {
            n = n.next;
        }
        Node name = n.next;
        n.next = name.next;
        N--;
        return name.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;
    }

反转整个链表

    /**
     * 用来反转整个链表
     */
    public void reverse() {
        // 判断当前链表是否为空链表
        if (isEmpty()) {
            return;
        }
        reverse(head.next);
    }

    /**
     * 反转指定的结点curr, 并把反转后的结点返回
     *
     * @param curr
     * @return
     */
    public Node reverse(Node curr) {
        if (curr.next == null) {
            head.next = curr;
            return curr;
        }
        // 递归的反转当前结点curr的下一个结点,返回值就是链表反转后,当前结点的上一个结点
        Node pre = reverse(curr.next);
        // 让返回结点的下一个结点变味当前结点curr
        pre.next = curr;
        // 把当前结点的下一个结点变为null
        curr.next = null;
        return curr;
    }

遍历整个链表

public class LinkList<T> implements ListMethods<T>, Iterable<T> {
    .....
    @Override
    public Iterator<T> iterator() {
        return new LIterator();
    }

    private class LIterator implements Iterator {
        private Node n;

        public LIterator() {
            this.n = head;
        }

        @Override
        public boolean hasNext() {
            return n.next != null;
        }

        @Override
        public Object next() {
            n = n.next;
            return n.item;
        }
    }
}

完整代码

package DataStrues.ListTable;

import java.util.Iterator;

public class LinkList<T> implements ListMethods<T>, Iterable<T> {
    private Node head;
    private int N;

    private class Node {
        T item;
        Node next;

        public Node(T item, Node next) {
            this.item = item;
            this.next = next;
        }
    }

    public LinkList() {
        this.head = new Node(null, null);
        this.N = 0;
    }

    @Override
    public void clear() {
        head.next = null;
        this.N = 0;
    }

    @Override
    public boolean isEmpty() {
        return N == 0;
    }

    @Override
    public int length() {
        return N;
    }

    @Override
    public T get(int i) {
        if(head.next == null) {
            return null;
        }
        Node n = head.next;
        for (int index = 0; index < i; index++) {
            n = n.next;
        }
        return n.item;
    }

    @Override
    public void insert(T t) {
        Node n = head;  // 把头节点复制给一个新元素
        while (n.next != null) {
            n = n.next;
        }
        n.next = new Node(t, null);
        N++;
    }

    @Override
    public void insert(int i, T t) {
        Node n = head;
        for (int index = 0; index < i; index++) {
            n = n.next;
        }
        n.next = new Node(t, n.next);
        N++;
    }

    @Override
    public T remove(int i) {
        Node n = head;
        for (int index = 0; index < i; index++) {
            n = n.next;
        }
        Node name = n.next;
        n.next = name.next;
        N--;
        return name.item;
    }

    @Override
    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;
    }

    /**
     * 用来反转整个链表
     */
    public void reverse() {
        // 判断当前链表是否为空链表
        if (isEmpty()) {
            return;
        }
        reverse(head.next);
    }

    /**
     * 反转指定的结点curr, 并把反转后的结点返回
     *
     * @param curr
     * @return
     */
    public Node reverse(Node curr) {
        if (curr.next == null) {
            head.next = curr;
            return curr;
        }
        // 递归的反转当前结点curr的下一个结点,返回值就是链表反转后,当前结点的上一个结点
        Node pre = reverse(curr.next);
        // 让返回结点的下一个结点变味当前结点curr
        pre.next = curr;
        // 把当前结点的下一个结点变为null
        curr.next = null;
        return curr;
    }

    @Override
    public Iterator<T> iterator() {
        return new LIterator();
    }

    private class LIterator implements Iterator {
        private Node n;

        public LIterator() {
            this.n = head;
        }

        @Override
        public boolean hasNext() {
            return n.next != null;
        }

        @Override
        public Object next() {
            n = n.next;
            return n.item;
        }
    }
}

posted @ 2024-03-06 17:25  ゐ叶う枫ゆ  阅读(5)  评论(0编辑  收藏  举报