Особый вид очереди - PullRequest
4 голосов
/ 21 марта 2010

Я ищу что-то вроде очереди, которая позволила бы мне поместить элементы в конец очереди и выдвинуть их в начале, как это делает обычная очередь.

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

e d . c . b . a
(this Queue has 8 items)

Затем мне нужно, например, удалить последнийточка, чтобы получить:

e d . c . b a

Есть ли что-нибудь подобное в классах Java Collection?Мне нужно использовать это для программы, которую я делаю, где я не могу использовать ничего, кроме классов Java.Мне не разрешено разрабатывать один для себя.В настоящее время я просто использую LinkedList, но я подумал, что, возможно, это будет больше похоже на очередь, чем на LinkedList.

Спасибо

edit:

По сути, вот что представляет собой проект: есть светофор, который может быть либо зеленым (и связанный с ним символ '-'), либо красным ('|').Этот светофор справа: альтернативный текст http://img684.imageshack.us/img684/9602/0xfhiliidyxdy43q5mageu0.png В начале у вас нет машин, а светофор зеленый, поэтому наш список представлен в виде:

.......  -

Теперь, на следующей итерации, у меня есть случайная переменная, которая сообщит мне, где находится машина или нет.Если приближается машина, то мы видим ее слева.На каждой итерации все машины движутся на один шаг вправо.Если у них есть машина справа от них, то они не могут двигаться:

a......  -   (iteration 1)
.a.....  -   (iteration 2)
..a....  -   (iteration 3)

и т. Д.

Теперь происходит то, что иногда светофор может стать красным ('-«).В этом случае, если у вас есть несколько автомобилей, то даже если у них будет некоторое расстояние между ними при движении, когда им придется остановиться на светофоре, они приблизятся:

...b.a.  -   (iteration n)
....b.a  -   (iteration n+1)
.....ba  -   (iteration n+2) here they got close to each other

Так вот, этопричина, по которой это работает как очередь, но иногда мне приходится снимать те точки, когда машины стоят возле красного светофора.Также имейте в виду, что размер улицы здесь составлял 7 символов, но иногда он увеличивается, поэтому мы не можем предполагать, что это список фиксированной длины.

Ответы [ 4 ]

4 голосов
/ 21 марта 2010

Очередь - это, в основном, список элементов с определенным поведением, в данном случае FIFO (First In First Out). Вы добавляете элементы в конце и удаляете их с самого начала.

Теперь очередь может быть реализована любым способом, который вы выберете; либо со связанным списком, либо с массивом. Я думаю, что вы на правильном пути. Связанный список определенно сделает это проще.

У вас будет O (1) для добавления и удаления в вашей очереди (если вы сохраняете ссылку на переднюю и заднюю часть), но в худшем случае для сжатия (удаления точки) будет O (п).

Я полагаю, что может быть способ уменьшить операцию compact до O (1) (если вы удаляете только одну точку за раз), если вы используете вторичную структуру данных. Вам нужна еще одна очередь (реализованная с использованием другого связанного списка), которая поддерживает ссылку на точки в первом связанном списке.

Итак, когда вы вставляете (a,., B, c,., D), у вас есть список, который выглядит так:

[pointer to rear] -> [d] -> [.] -> [c] -> [b] -> [.] -> [a] <- [pointer to front]

и у вас также есть вторичная очередь (реализованная в виде связанного списка), в которой хранится ссылка на точку:

[pointer to rear] -> [reference to second dot] -> [reference to first dot] <- [pointer to front]

Затем, когда вам нужно выполнить операцию compact, все, что вам нужно сделать, это удалить первый элемент из второй очереди и сохранить ссылку. Итак, теперь у вас есть ссылка на точку, которая находится в середине первого связанного списка. Теперь вы можете легко удалить эту точку из первого списка.

Вы упомянули в комментарии, что вам нужно следить за заказом. Очередь по определению является упорядоченной структурой (в том смысле, что вещи остаются в том порядке, в котором они были вставлены). Поэтому все, что вам нужно сделать, это вставить ссылку на точку во вторую очередь, когда вы вставите точку в первую. Таким образом, порядок поддерживается. Поэтому, когда вы извлекаете ссылку на точку из второй очереди, вы получаете ссылку на фактическую и соответствующую точку в первой очереди.

Компромисс в скорости заключается в том, что вам нужно больше памяти, потому что вы поддерживаете второй список ссылок. В худшем случае требования к памяти в 2 раза больше, чем вы используете сейчас. Но это достойный компромисс, чтобы получить O (1) против O (n).

3 голосов
/ 21 марта 2010

Домашние задания / школьные проекты всегда сложны, добавляя тонкие вещи к требованиям, которые могут заставить чей-то мозг растаять. Есть ли у вас какие-либо требования включать пробелы в очередь?

Лично я бы не стал этого делать, если бы не было явного требования: кажется, что проще представить ваши машины как пары Car, Space (вы можете определить пару как структуру, предполагая, что вам разрешено использовать структуры), где пространство является числовое значение, представляющее пространство в направлении следующего автомобиля в транспортном средстве. Затем, чтобы сжать, вам нужно только просмотреть элементы списка: когда вы найдете тот, который имеет Space > 0, выполните Space--; return;, и все другие автомобили будут уже «продвинутыми», так как они сохраняют пространство с теми, что в перед ними. Для вывода убедитесь, что выбрасываете Space точек для каждого автомобиля после (если стоп-сигнал справа, а автомобили идут слева) или перед (стоп-сигнал слева и автомобили, идущие справа) самого автомобиля, и там вы идете. Также обратите внимание, что Space первого автомобиля представляет расстояние до самого стоп-сигнала, так как до него нет автомобиля.

Если вы добавите в структуру указатель на следующий вагон (и нулевой указатель на последний вагон), у вас уже есть связанный список: сохраните «глобальную» переменную, которая указывает на первый вагон (или ноль для пустая очередь). Поскольку Java напрямую не поддерживает указатели, превратите структуру в класс и используйте «ссылки на объекты» (которые аналогичны указателям для всех целей, кроме арифметики указателей на C'ish), и все: только один класс, встроенный с нуля. Единственное, что вам нужно затронуть в библиотеках Java, - это стандартный ввод-вывод и, возможно, небольшая манипуляция со строками, которая является неотъемлемой потребностью, возникающей из-за необходимости принимать ввод и производить вывод (некоторые колледжи имеют свой собственный ввод-вывод для конкретного курса библиотеки, но это не имеет большого значения здесь). Чтобы перебрать очередь, вы должны сделать что-то вроде этого (если предположить, что класс называется «Node», что является довольно общим, и очевидные имена для полей):

for(Node pos = First; pos != null; pos = pos.Next) {
    /* Do your stuff here, knowing that "pos" points to the "current" item on each iteration. */
}

Чтобы добавить новые узлы, вам, вероятно, придется пройти через очередь, чтобы выяснить, на каком расстоянии от последнего появится новый автомобиль; когда вы делаете это, сохраняйте ссылку с последнего узла и делайте его "следующую" контрольную точку с новым узлом:

Node last = First;
int distance = 0;
for(Node pos = First; pos != null; pos=pos.Next) {
    distance += pos.Space;
    last = pos;
}
last.Next = new Node(the_letter_for_this_car, MaxDistance-distance, null);

Конечно, настройте конструктор на то, что у вас есть.

Учитывая, что это проект колледжа, давайте посмотрим на некоторые детали: компактное время процесса становится O(n), а его использование памяти - O(0) (самому процессу не нужны никакие "локальные" переменные, другие чем, может быть, указатель для обхода коллекции, которая не зависит от длины очереди.) Кроме того, использование памяти для самой очереди гарантированно будет меньше или равно тому, что было бы для представления пробелов в качестве элементов (он получает только чтобы быть равным в худшем случае, когда достаточно много автомобилей застряли на красный свет). Поэтому, если в требования не входит что-то несовместимое с этим подходом, я бы ожидал, что именно этого хотят ваши учителя: это аргументировано, эффективно и соответствует тому, о чем вас просили.

Надеюсь, это поможет.

3 голосов
/ 21 марта 2010

Я бы сказал, что LinkedList будет лучшим подходом здесь ... поскольку LinkedList позволяет вам нажимать / выдвигать спереди / сзади и позволяет удалять элемент в середине списка.

Очевидно, что время поиска отстой, но если вы добавляете / удаляете из передней / задней части списка чаще, чем просматриваете, то я бы сказал, что придерживайтесь LinkedList.

1 голос
/ 21 марта 2010

Может быть, второй LinkedList, который содержит элемент точка?

...