Не удается устранить ошибки итерации Java Deque - PullRequest
0 голосов
/ 04 ноября 2019

Во время тестирования я обнаружил ошибки в своем коде.

У меня возникли проблемы с обнаружением, что не так с моим Deque Итератором. Это не повторяется должным образом, и я понятия не имею, как это исправить. Я включил снимки экрана с ошибочными тестами и мой законченный код.

Примечание: Мой профессор хочет, чтобы итератор Элементы Dequeue изголова при итерации вперед ИЛИ итерация назад, поэтому итератор немного сложнее понять.

Скриншоты с ошибочными юнит-тестами: https://imgur.com/a/srlmrNQ

СпасибоВы так много за помощь!

Полный исходный код:

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

public class Deque<E> implements Iterable<E>
{
    private class DequeNode<E>
    {
        private DequeNode<E> _next;
        private DequeNode<E> _previous;
        private E _data;

        private DequeNode(E data)
        {
            _data = data;
        }
    }

    private DequeNode<E> _head;
    private DequeNode<E> _tail;
    private int _depth;
    private static final int EXCLUSIVE_INDEX_START = -1;


    public Deque()
    {
        _head = null;
        _tail = null;
        _depth = 0;
    }

    public boolean enqueue(E element) // This is INSERTION at the TAIL //TODO: DONE!!
    {
        DequeNode<E> newNode = new DequeNode<E>(element);

        if (isEmpty())
        {
            _head = newNode;
        }
        else
        {
            _tail._next = newNode;
            newNode._previous = _tail;
        }
        _tail = newNode;
        _depth++;

        return true;
    }

    public void enqueueAll(Iterable<E> elements)
    {
        for (E eachElement : elements)
        {
            enqueue(eachElement);
        }
    }

    public boolean enqueueHead(E element) // This is insertion at the head //TODO: DONE!!
    {
        DequeNode<E> newNode = new DequeNode<E>(element);

        if (isEmpty())
        {
            _tail = newNode;
        }
        else
        {
            _head._previous = newNode;
            newNode._next = _head;
        }
        _head = newNode;
        _depth++;

        return true;
    }

    public E head()
    {
        checkForStackUnderflow();
        return _head._data;
    }

    public E tail()
    {
        checkForStackUnderflow();
        return _tail._data;
    }

    public E dequeue() // This is removal at the head //TODO: DONE!!
    {
        checkForStackUnderflow();

        E removed = _head._data;

        if (_head._next == null)
        {
            _tail = null;
        }
        else
        {
            _head._next._previous = null;
        }
        _head = _head._next;
        _depth--;

        return removed;
    }

    public E dequeueTail() // This is removal at the tail //TODO: DONE!!
    {
        checkForStackUnderflow();

        E removed = _tail._data;

        if (_head._next == null)
        {
            _head = null;
        }
        else
        {
            _tail._previous._next = null;
        }
        _tail = _tail._previous;
        _depth--;

        return removed;
    }

    public void clear()
    {
        _head = _tail = null;
        _depth = 0;
    }

    public int depth()
    {
        return _depth;
    }

    public boolean isEmpty()
    {
        return _depth == 0;
    }

    public Iterator<E> iterator()
    {
        return new DequeIterator(this, false);
    }

    public Iterator<E> reverseIterator()
    {
        return new DequeIterator(this, true);
    }

    private void checkForStackUnderflow()
    {
        if (isEmpty())
        {
            throw new NoSuchElementException("Stack underflow captain!!!");
        }
    }

    private class DequeIterator implements Iterator<E>
    {
        // The instance variables used throughout the program.
        private int _index;
        private Deque<E> _theList;
        private DequeNode<E> _current;
        private boolean _iterateReverse;


        public DequeIterator(Deque<E> deque, boolean reverse)
        {
            _theList = deque;
            _iterateReverse = reverse;
            _index = 0;
            _current = _head;

            /* If the flag for reverse iteration is detected, then just start
            the index at the end and iterate from the tail.
             */
            if (reverse)
            {
                _index = _theList._depth - 1;
                _current = _theList._tail;
            }
        }

        public boolean hasNext()
        {
            boolean results;

            // If we are reverse iterating check if the index is > than -1.
            if (_iterateReverse)
            {
                results = _index > EXCLUSIVE_INDEX_START;
            }
            /* Getting here means that we are forward iterating so check if the
            index is less than size AKA if we have more elements to go through.
             */
            else
            {
                results = _index < _theList._depth;
            }
            return  results;
        }


        public E next()
        {
            // If we don't have more elements to iterate through then we throw.
            if (!hasNext())
            {
                throw new NoSuchElementException();
            }
            // Update the current to descent if we are reverse iterating.
            if (_iterateReverse)
            {
                _current = _current._previous;
                _index--;
            }
            // If we get to here then just update the current value forward.
            else
            {
                _current = _current._next;
                _index++;
            }

            return dequeue();
        }
    }
}

1 Ответ

1 голос
/ 05 ноября 2019

Поскольку код обновляет значение индекса на каждой итерации и уменьшает значение глубины при каждой операции удаления из очереди итерации, возникает случай использования, когда глубина меньше значения индекса, поэтому возвращается неправильное значение hasNext () (котороепохоже, является основной причиной всех неудачных тестовых сценариев.)

Простой способ реализации hasNext () будет следующим:

return _theList._depth> 0;

Это будет работать для описанного выше варианта использования, поскольку в каждой операции next () выполняется операция dequeue () (которая уменьшает значение глубины).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...