背包
在《算法》中,作者实现了一个初级集合,使用了最初级的单链表,集合命名为背包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,只是又对应的添加了些方法。
光学不练,假把式。
请一定记得动手操作呦~