(См. также следующую итерацию.)
(Эта структура данных может быть реализована как Deque<List<T>>
, все же я решил иметь некоторое лучшее время с этим. :-))
com.github.coderodde.util.Multistack.java:
package com.github.coderodde.util;
import java.util.ArrayList;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
/**
* This class implements a stack of lists.
*
* @author Rodion "rodde" Efremov
* @version 1.6 (Feb 8, 2023)
* @since 1.6 (Feb 8, 2023)
*/
public final class Multistack<T> implements Iterable<List<T>> {
private static final class MultistackIterator<T>
implements Iterator<List<T>> {
private final Multistack<T> stack;
private final long expectedModCount;
private MultistackNode<T> currentNode;
MultistackIterator(Multistack<T> stack) {
this.stack = stack;
this.expectedModCount = stack.modCount;
this.currentNode = stack.top;
}
@Override
public boolean hasNext() {
checkModCount();
return currentNode != null;
}
@Override
public List<T> next() {
checkModCount();
List<T> list = currentNode.extract();
currentNode = currentNode.next;
return list;
}
private void checkModCount() {
if (expectedModCount != stack.modCount) {
throw new ConcurrentModificationException(
"Multistack changed while iterating.");
}
}
}
@Override
public Iterator<List<T>> iterator() {
return new MultistackIterator<>(this);
}
private static final class Node<T> {
private final T datum;
private Node<T> next;
Node(T datum) {
this.datum = datum;
}
}
private static final class MultistackNode<T> {
private final Node<T> head;
private Node<T> tail;
private final MultistackNode<T> next;
private int size = 0;
public MultistackNode(T datum, MultistackNode<T> top) {
Node<T> node = new Node<>(datum);
head = node;
tail = node;
size = 1;
next = top;
top = this;
}
void append(Node<T> node) {
tail.next = node;
tail = node;
size++;
}
List<T> extract() {
List<T> list = new ArrayList<>(size);
for (Node<T> node = head; node != null; node = node.next) {
list.add(node.datum);
}
return list;
}
}
private int size;
private long modCount;
private MultistackNode<T> top;
public void push(T datum) {
MultistackNode node = new MultistackNode(datum, top);
top = node;
size++;
modCount++;
}
public void linkToTop(T datum) {
if (size == 0) {
throw new NoSuchElementException(
"Trying to link a datum to an empty Multistack. " +
"Please push an element before doing this operation.");
}
top.append(new Node<>(datum));
modCount++;
}
public List<T> peek() {
if (size == 0) {
throw new NoSuchElementException(
"Peeking from an empty Multistack.");
}
return top.extract();
}
public List<T> pop() {
if (size == 0) {
throw new NoSuchElementException(
"Popping from an empty Multistack.");
}
List<T> returnValue = top.extract();
top = top.next;
size--;
modCount++;
return returnValue;
}
public int size() {
return size;
}
public boolean isEmpty() {
return size == 0;
}
public static void main(String[] args) {
Multistack<Integer> stack = new Multistack<>();
stack.push(1);
stack.push(2);
stack.linkToTop(3);
stack.linkToTop(4);
stack.push(5);
stack.linkToTop(6);
stack.push(7);
for (List<Integer> level : stack) {
System.out.println(level);
}
}
}
Демонстрационный вывод
[7]
[5, 6]
[2, 3, 4]
[1]
Запрос критики
Есть что улучшить? Пожалуйста, скажите мне.
кодродде