数据结构-链表

来源:互联网 发布:50量子计算机 ibm 知乎 编辑:程序博客网 时间:2024/05/16 16:20

链表

链表是链式存储的集合数据结构,节点与节点之间通过记录地址来联系,对于经常需要增删的数据结构,以链表为基础实现会比数组实现高很多。

分析要求

1. 支持泛型2. 可迭代3. 尽量高效

其实要实现一个节点,只需要声明一个包含存储对象和存储地址的抽象数据类型即可,如下:

private class Node<Item> {    public Node(Item item) {this.item = item;}    private Item item;    private Node next;}

接口设计

public interface LinkedListInterface<Item> extends Iterable<Item> {//支持迭代    /** 插入节点 */    void add(int idx, Item item);    /** 删除节点 */    Item remove(int idx);}

单向实现

public class LinkedList<Item> implements LinkedListInterface<Item> {    private Node firstNode = new Node(null);//第一个节点不存储数据,只是作为链表开始的标志    public int length = 0;//链表长度    public void add(int idx, Item item) {//插入        Node pre = getPreNodeByIndex(idx);        Node node = new Node(item);        node.next = pre.next;        pre.next = node;        length++;    }    public Item remove(int idx) {//移除        Node pre = getPreNodeByIndex(idx);        Node del = pre.next;        if (del == null) throw new IndexOutOfBoundsException("" + idx);        pre.next = pre.next.next;        length--;        return del.item;    }    public Item get(int idx) {//获取        Node curr = getPreNodeByIndex(idx).next;        if (curr == null) throw new IndexOutOfBoundsException("" + idx);        return curr.item;    }    public Iterator<Item> iterator() {//实现迭代        return new Iterator<Item>() {            private Node currNode = firstNode;            public boolean hasNext() {return currNode.next != null;}            public Item next() {                currNode = hasNext() ? currNode.next : currNode;                return currNode.item;            }            public void remove() {}        };    }    /** 获取该索引所对应的节点的前驱 */    private Node getPreNodeByIndex(int idx) {        if (idx < 0) throw new IndexOutOfBoundsException("" + idx);        Node pre = firstNode;        for (int i = 0; i < idx; i++) {            pre = pre.next;            if (pre == null) throw new IndexOutOfBoundsException("" + idx);        }        return pre;    }}

双向实现

相比较于单向实现,双向实现中的每一个节点不仅需要记录它的后继节点,还应记录它的前驱节点的地址,因此空间开销会变大,但是可以解决单向链表操作链表尾端时低效的问题,不用遍历至链表尾部即可操作。

//TODO  抽空写
0 0
原创粉丝点击