链表之初级集合(背包)实现

23 阅读2分钟

背包

在《算法》中,作者实现了一个初级集合,使用了最初级的单链表,集合命名为背包Bag,它不支持从中删除元素,目的就是收集元素并且可以迭代所有元素。

该集合属于后进先出,其实顺序在此不敏感,并不像Java中的ArrayList, 打个比方,它就像一个塑料袋,将玻璃珠(元素)装在里面,对取出的顺序不关注,因此,如果场景中对顺序没要求的任务可以使用它来做统计,如计算标准差等。当然我们也可以在背包中寻找具有某个特点的玻璃珠,必要时可以通过forEach遍历查找所有玻璃珠(元素)。

作为一个基础结构,目前看来它的用处还很有限,单与之前我在博文中提到的一样,它是复合数据结构中的基础,只要把基础结构搞的明明白白,才能学好复合数据结构。

设计思路与实现

因为同下压栈一样都是后进先出的结构,所以设计思路大同小异,都采用了链表,只不过将stack中的pop方法去掉了,我们直接看代码实现:

package com.magic.school.hogwarts.design.algorithm.api.one.bag;

import org.jetbrains.annotations.NotNull;

import java.util.Iterator;
import java.util.NoSuchElementException;

public class Bag<Item> implements Iterable<Item> {
    /**
     * 元素数量
     */
    private int size;
    /**
     * 首结点
     */
    private Node first;

    /**
     * 栈结构保存数据
     */
    private class Node {
        Item item;
        Node next;
    }

    /**
     * 为实现遍历我们用内部类实现Iterator接口
     */
    private class BagIterator implements Iterator<Item>{
        private Node current = first;
        @Override
        public boolean hasNext() {
            return current!=null;
        }

        @Override
        public Item next() {
            if (!hasNext()){throw new NoSuchElementException("Bag is Empty!");}
            Item item = current.item;
            current = current.next;
            return item;
        }
    }

    /**
     * 添加元素
     * @param item
     */
    public void add(Item item){
        //从首结点添加
        Node oldFirst = first;
        first = new Node();
        first.item = item;
        first.next = oldFirst;
        size++;
    }

    /**
     * 获取背包内元素数量
     * @return
     */
    public int size(){return size;}

    /**
     * 是否null背包
     * @return
     */
    public boolean isEmpty(){
        return first == null;
    }

    /**
     * 通过iterator遍历元素
     * @return
     */
    @Override
    public Iterator<Item> iterator(){
        return new BagIterator();
    }

    public static void main(String[] args) {
        Bag<Integer> bag = new Bag<>();
        for (int i = 0; i < 1000; i++) {
            bag.add(i);
        }
        Iterator<Integer> iterator = bag.iterator();
        int sum = 0;
        while (iterator.hasNext()) {
            int num = iterator.next();
            System.out.println(num);
            sum += num;
        }
        System.out.println("============================");
        System.out.println("sum: " + sum);
    }
}

单看这个Bag确实有些单薄、简单,等我们封装复合数据类型时就可以看到它的威力了。 我们在内部类实现的是Iterator接口,java类库中LinkedList的内部类实现的是ListIterator 但这个接口同样继承了Iterator,只是又对应的添加了些方法。

光学不练,假把式。

请一定记得动手操作呦~