数据结构-链表

链表

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

分析要求

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值