![]() |
Модераторы: volvo877, Snowy, MetalFan |
![]() ![]() ![]() |
|
BSOD |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 405 Регистрация: 1.11.2004 Где: Гомель Репутация: нет Всего: 3 |
Люди, объясните человеку, начинающему учить паскаль, что такое очередь, как ей пользоваться и для чего она нужна.....
тока плз по доходчивей ![]() ![]() -------------------- как корабль назовешь - то на нем и напишешь |
|||
|
||||
SPrograMMer |
|
||||
![]() Спамер :) ![]() ![]() Профиль Группа: Участник Сообщений: 442 Регистрация: 5.11.2004 Где: Краснодар Репутация: нет Всего: 6 |
Очередь - это набор идущих друг за другом объектов.Представь себе длинный-длинный коридор, на правую сторону этого коридора находятся комнаты 1, 2, 3 и т д - это элементы очереди.Но только вот двери в этих комнатах странные... Ты можешь зайти сразу только в первую комнату, а для того что бы попасть во-вторую - тебе надо пройти эту первую комнату.Во второй комнате есть дверь в третью... и т д.Что бы выйти наконец из коридора, тебе надо пройти все эти комнаты.
Да, чуть не забыл очередь реализуется на основе указателей (ссылок), ну так вот дверь в очередную комнату - это ссылка на этот самый следующий элемент очереди. Теперь о типах очередей. Конечно, классическое действие очереди формулируется как "Первым зашёл, последним вышел", но на практике иногда бывает полезно это классическое определение "стереть в порошок", и необращать на него ни малейшего внимания. Таким образом моно выделить следующие типы очередей: 1)однонаправленные - это когда движешься от начала очереди в конец последовательно, а как пройдешь очередную комнату - дверь назад... пропадает :), и назад пути нету (Вперед, и только вперед - к победе!) - это и есть классическая очередь. При реализации такой очереди в программе хранится только указатель на первый объект очереди (дверь в первую комнату). Для доступа, например, к 5-ому элементу, необходимо (без этого никак!!!) пройти все предыдущие элементы очереди. При этом в самой записи (элементе очереди) хранится кроме полезной информации, есчо и ссылка (указатель) на следующий элемент. 2)двунаправленные - тут уж как хочешь: пройдешь пять дверей вперед, потом захотел вурнуться - пожалуйста, без проблем, этакое реверсивное движение. При реализации такой очереди обычно хранится уже две переменные - "голова" и "хвост" очереди. Хотя вполне можно ограничиться только "Головой". В самой записи находится уже два указателя: на предыдущий элемент и на следующий. Первый элемент очереди ссылки на предыдущий элемент не имеет (на паскале ставиться "пустое значение указателя" - Nil), а послений элемент - ссылки на следующий не имеет и вместо него ставится Nil 3)многонаправленные - ну тут уж совсем сложно: из одной комнаты, можно попасть не только в следующую или предыдущую конаты, а моно пойти налево, или направо - а там свои коридоры с точно такими же комнатами... (так например можно представить плоскую доску, например, шахматную, где с текущей клетки моно пойти по 8 направлениям [если она конечно не граничная]). В реализации одного элемента такой очереди могут участвовать не два (как в предыдущем случае), а большее количество указателей. Непосредственно - примеры реализации очередей и работа с ними: I-ый тип очередей как я уже говорил, все это дело на основе указателей (чеще всего на записи). Структура такой записи такая: рабочие данные (комната) + ссылки (двери). Сколько будет ссылок, зависит от выбранного типа очереди. Пример:
Первоначально, в очереди нет ни одного элемента, => в First должно быть Nil. Несмотря на то что вроде как утверждается, что многие паскаль-компиляторы при объявлении переменной указателя автоматом засовывают туда Nil, я много раз убеждался, что это не так. Поэтому перед началом работы лучше выполнить следующую команду:
Ну теперь давайте по добавляем элементы в очереь. Так как у нас только "голова очереди", то придется добавлять только в начало очереди, постепенно "удаляя" уже существующие элементы от головы к хвосту очереди. Делать это лучше в подпрограмме: [code=delphi] Procedure Add(S:String;C:Integer); // в подпрограмму передаются тольк Это сообщение отредактировал(а) SPrograMMer - 14.4.2005, 16:38 |
||||
|
|||||
Fedor |
|
||||
![]() Днепрянин ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 2090 Регистрация: 8.2.2003 Где: Великий Репутация: нет Всего: 32 |
Очередь - это такая особая структура данных. Работает она по принципу FIFO (First In - First Out). В переводе на обычный язык, это означает, что елемент, добалвенный первым, первым оттудова и выйдет.
Пример: Приходишь ты в магазин, а там самая обычная очередь. Ты стал в очередь. За тобой пришел и стал еще один человек. Ты пришел первее него, значит и выйдешь первее. Очередь как структура данных работает точно так же: ты добавил какой-то элемент в очередь, значит он будет потом обработан после элементов, которые там уже были и перед элементами которые прийдут посел него. Теперь как это реализовывается в Паскале: Я предпочитаю реализацию с помощью обычного одномерного массива (ИМХО, это легче), хотя вполне можно и с помощью динамических структур данных (это экономит память). Я покажу, как с массивами, но если нужно, расскажу и как с динамическими структурами это сделать. 1) Переменные:
2) Процедуры и функции для работы с очередью:
Конечно, можно еще напридумывать ф-ции например поиска или удаления елемента из середины, но это не сложно. Будут вопросы, задавай ![]() Добавлено @ 22:21 Блин, пока писал, уже ответили.... ![]() Добавлено @ 22:22 За то заодно исть и реализация с помощью динамических структур ![]() -------------------- Мы - Днепряне. Мы всех сильней. |
||||
|
|||||
Fedor |
|
|||
![]() Днепрянин ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 2090 Регистрация: 8.2.2003 Где: Великий Репутация: нет Всего: 32 |
maximum так помогли тебе или нет? Я просто хочу эту тему в FAQ, важно твое мнение об усвояемости и о наличии ошибок
![]() -------------------- Мы - Днепряне. Мы всех сильней. |
|||
|
||||
Zero |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2169 Регистрация: 23.10.2004 Где: Россия, г. Рязань Репутация: нет Всего: 24 |
Fedor помоему то как написано у SPrograMMer, понятнее не напишешь. И ИМХО динамические структуры более подходят для очереди. Хотя в отдельных случаях можно и так как у тебя.
|
|||
|
||||
SPrograMMer |
|
|||
![]() Спамер :) ![]() ![]() Профиль Группа: Участник Сообщений: 442 Регистрация: 5.11.2004 Где: Краснодар Репутация: нет Всего: 6 |
Ну коли так я еще это дело подредактировать могу, да поподробнее написать, примеров там побольше,например.
Надо? Это сообщение отредактировал(а) SPrograMMer - 14.4.2005, 12:19 -------------------- животное = зверь законченный гентушник |
|||
|
||||
SPrograMMer |
|
|||
![]() Спамер :) ![]() ![]() Профиль Группа: Участник Сообщений: 442 Регистрация: 5.11.2004 Где: Краснодар Репутация: нет Всего: 6 |
![]() ![]() ![]() Ну и бог с ним ![]() СЧас чё нить придумаю... -------------------- животное = зверь законченный гентушник |
|||
|
||||
Fedor |
|
||||||
![]() Днепрянин ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 2090 Регистрация: 8.2.2003 Где: Великий Репутация: нет Всего: 32 |
Надо. ![]()
Не было ![]()
Если что, мне на мыло высылай. -------------------- Мы - Днепряне. Мы всех сильней. |
||||||
|
|||||||
SPrograMMer |
|
|||
![]() Спамер :) ![]() ![]() Профиль Группа: Участник Сообщений: 442 Регистрация: 5.11.2004 Где: Краснодар Репутация: нет Всего: 6 |
млин, уже полчаса как пытаюсь - нуль дисконектовский. Значит завтра, т е 15.04.2005, ожидай с 8-30 по 10-00. вышлю! -------------------- животное = зверь законченный гентушник |
|||
|
||||
BSOD |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 405 Регистрация: 1.11.2004 Где: Гомель Репутация: нет Всего: 3 |
Мне версия SPrograMMer больше монравилась, а в FAQ давно пора... ![]() -------------------- как корабль назовешь - то на нем и напишешь |
|||
|
||||
Fedor |
|
|||
![]() Днепрянин ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 2090 Регистрация: 8.2.2003 Где: Великий Репутация: нет Всего: 32 |
Ок. Завтра когда пришлет, добавлю в FAQ ![]() -------------------- Мы - Днепряне. Мы всех сильней. |
|||
|
||||
SPrograMMer |
|
|||
![]() Спамер :) ![]() ![]() Профиль Группа: Участник Сообщений: 442 Регистрация: 5.11.2004 Где: Краснодар Репутация: нет Всего: 6 |
Ну раз ни как не получается схитрю: буду постить сюда маленькими порциями.
Вот первая: Очередь - это набор идущих друг за другом объектов.Представь себе длинный-длинный коридор, на правую сторону этого коридора находятся комнаты 1, 2, 3 и т д - это элементы очереди.Но только вот двери в этих комнатах странные... Ты можешь зайти сразу только в первую комнату, а для того что бы попасть во-вторую - тебе надо пройти эту первую комнату.Во второй комнате есть дверь в третью... и т д.Что бы выйти наконец из коридора, тебе надо пройти все эти комнаты. Да, чуть не забыл очередь реализуется на основе указателей (ссылок), ну так вот дверь в очередную комнату - это ссылка на этот самый следующий элемент очереди. Теперь о типах очередей. Конечно, классическое действие очереди формулируется как "Первым зашёл, последним вышел", но на практике иногда бывает полезно это классическое определение "стереть в порошок", и необращать на него ни малейшего внимания. Таким образом моно выделить следующие типы очередей: 1)однонаправленные - это когда движешься от начала очереди в конец последовательно, а как пройдешь очередную комнату - дверь назад... пропадает ![]() При реализации такой очереди в программе хранится только указатель на первый объект очереди (дверь в первую комнату). Для доступа, например, к 5-ому элементу, необходимо (без этого никак!!!) пройти все предыдущие элементы очереди. При этом в самой записи (элементе очереди) хранится кроме полезной информации, есчо и ссылка (указатель) на следующий элемент. 2)двунаправленные - тут уж как хочешь: пройдешь пять дверей вперед, потом захотел вурнуться - пожалуйста, без проблем, этакое реверсивное движение. При реализации такой очереди обычно хранится уже две переменные - "голова" и "хвост" очереди. Хотя вполне можно ограничиться только "Головой". В самой записи находится уже два указателя: на предыдущий элемент и на следующий. Первый элемент очереди ссылки на предыдущий элемент не имеет (на паскале ставиться "пустое значение указателя" - Nil), а послений элемент - ссылки на следующий не имеет и вместо него ставится Nil 3)многонаправленные - ну тут уж совсем сложно: из одной комнаты, можно попасть не только в следующую или предыдущую конаты, а моно пойти налево, или направо - а там свои коридоры с точно такими же комнатами... (так например можно представить плоскую доску, например, шахматную, где с текущей клетки моно пойти по 8 направлениям [если она конечно не граничная]). В реализации одного элемента такой очереди могут участвовать не два (как в предыдущем случае), а большее количество указателей. Это сообщение отредактировал(а) SPrograMMer - 15.4.2005, 19:17 -------------------- животное = зверь законченный гентушник |
|||
|
||||
SPrograMMer |
|
||||||||||||||||||||||||||
![]() Спамер :) ![]() ![]() Профиль Группа: Участник Сообщений: 442 Регистрация: 5.11.2004 Где: Краснодар Репутация: нет Всего: 6 |
примеры реализации очередей и работа с ними:
I-ый тип очередей как я уже говорил, все это дело на основе указателей (чеще всего на записи). Структура такой записи такая: рабочие данные (комната) + ссылки (двери). Сколько будет ссылок, зависит от выбранного типа очереди. Пример:
Первоначально, в очереди нет ни одного элемента, => в First должно быть Nil. Несмотря на то что вроде как утверждается, что многие паскаль-компиляторы при объявлении переменной указателя автоматом засовывают туда Nil, я много раз убеждался, что это не так. Поэтому перед началом работы лучше выполнить следующую команду:
Ну теперь давайте по добавляем элементы в очереь. Так как у нас только "голова очереди", то придется добавлять только в начало очереди, постепенно "удаляя" уже существующие элементы от головы к хвосту очереди. Делать это лучше в подпрограмме:
При удалении элемента нужно помнить, что если мы удалим головной элемент (голову) очереди, то мы все равно должны дать возможность обращаться к следующему за удаляемым элементу, то есть теперь второй элемент очереди становится первым - головой. Опять таки лучше оформить это в виде подпрограммы:
А если надо очистить ВЕСЬ список то вот рецепт:
Добавлено @ 19:19 Ну и что бы были раждости полные штаны давайте рассмотрим пример, работы со всеми элементами очереди. Например, увеличение каждого Chislo на 1 и вывод на печать всех Data. Для этого надо будет пройтись по всему списку (примерно так как было при удалении всех элементов) от начала до конца,получится примерно следующий код:
При вставке элемента где-нить по середине нужно помнить, что при этом мы должны сохранить целостность списка, что бы не получилось так, что некотрые эл-ты у нас потеряются. Например, вот так может выглядеть вставка эл-та в n-ую позицию:
Для таких "сложных" манипуляций с элементами очереди лучше представлять что мы делаем. Сейчас попробую обяснить зачем нам понадобился PredItem - ссылка на предыдущий эл-т. Пусть наша очередь: First -> 1 -> 2 -> 3 -> 4 -> nil Как видно всего у нас четыре эл-та и вставляем мы новый эл-т на место 3-его. Сразу мы "видим" только первый элемент (переменная First) После добавления добавления долна получится следующая картина: First -> 1 -> 2 -> 5 -> 3 -> 4 -> nil То есть после второго эл-та у нас должен идти 5-ый (только-что вставленный на 3-ье место), а после него - 3-ий. Т к очередь у нас классическая и ссылок на предыдущие эл-ты нет, то на момент нахождения 3-ео элемента, у нас будет следующее: CurItem -> 3 -> 4 -> nil и First -> 1 -> 2 -> 3 -> 4 -> nil Естественно мы можем создать новый эл-т и в его поле Next запихнуть то что содержится в CurItem:
NewItem -> 5 -> 3 -> 4 -> nil CurItem -> 3 -> 4 -> nil First -> 1 -> 2 -> 3 -> 4 -> nil это то что у нас получится с переменными. сделать переход ...-> 2 -> 5 -> .... не представляется возможным, поэтому и пришлось использовать еще одну переменную, в которую запоминался предыдущий эл-т. Тогда, на момент выполнения всех действий у нас бедет следующая картина: NewItem -> 5 -> 3 -> 4 -> nil CurItem -> 3 -> 4 -> nil PredItem -> 2 -> 3 -> 4 -> nil First -> 1 -> 2 -> 3 -> 4 -> nil Вот используя PredItem^.Next (Это и есть наша связка 2 ->) и реализовали нашу задачу. Ну вот кажись и все насчет первого типа очередей. продолжение следует... Добавлено @ 19:20 II-ый тип очередей Тип записи следующий:
Как раньше договаривались, перед началом делаем:
Теперь, когда у нас два указателя, процедура добавления может выгладеть двояко:
Вставка в серёдку:
Закорючка. На первый взляд выражение CurrItem^.Next^.Pred или CurrItem^.Pred^.Next вызывает недоумение. Что это вообще такое и с чем его едят, а может быть это одно и тоже? Спокойно! Счас всё объясню. Представляем снова наши диаграмки. Например у нас очередь из четырех - элементов. (Не забываем что очередь двунаправленная): First->1->2->3->4->nil nil<-1<-2<-3<-4<-Last Например, мы вставляем новый элемент после 2-ого, т е у нас должно получиться: First->1->2->5->3->4->nil nil<-1<-2<-5<-3<-4<-Last То что после первого же прогона цыкла While в переменной CurItem Будет наш второй эл-т, я думаю ясно. Что происходит далее: Создаётся новый элемент: NewItem->5->Nil (next) (pred) Nil<-5 Затем начинают формироваться ссылки на другие эл-ты очереди, и ссылки элементов очереди (следующего и предыдущего) на новый элемент. Строка NewItem^.Next:=CurrItem^.Next; приведет к следующему: NewItem->5->3->.... (next) (pred) Nil<-5 Хотя ссылка на предыдущий эл-т третьего эл-та остаётся прежней: ...<-2<-3<-... первая закорючка CurrItem^.Next^.Pred:=NewItem делает ссылку на новый элемент в качестве предыдущего элемента для следующего, относительно текущего: ( ![]() ![]() ![]() Текущий элемент: <-2->, его следующий(3): <-3-> ну так вот изменяется связь <-3, предыдущий для третьего становится новый элемент: ...->2->3-> nil<-5<-3<- после этих двух строчек связи ...2->3.. ...2<-3.. теряются и на их место становятся: ...2... 5->3... ...2... 5<-3... как видите двойка у нас еще в неопределенности, а нам надо, что бы после двойки была 5, а до 5 - двойка. Что и делают следующие строчки: CurrItem^.Next:=NewItem; NewItem^.Pred:=CurrItem; После первой из них: ...2->5->3... ..2.. 5->3.. Ну и после второй: ...2->5->3... ...2<-5->3.. Получили то к чему стремились. ![]() Добавлено @ 19:27 Ну а для просмотра всех элементов можно опять-таки поступить двояко: идти от начала к концу или от кноца к началу. Благо у нас теперь есть два указателя!
Аналогично можно сделать и удаление всех элеме -------------------- животное = зверь законченный гентушник |
||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||
SPrograMMer |
|
||||||
![]() Спамер :) ![]() ![]() Профиль Группа: Участник Сообщений: 442 Регистрация: 5.11.2004 Где: Краснодар Репутация: нет Всего: 6 |
Тута был глюк с дисконектом
Аналогично можно сделать и удаление всех элементов: или от начала, или от конца. При удалении одного элемента, нужно помнить, что должны остаться переходы от предыдущего элемента к следующему и от следующего к предыдущему:
ну вот и очереди второго типа вроде разобрались. III-ый тип очередей Тип записи (количество ссылок) зависит от задачи. Например, в случае решения какой-нить задачи, связанной с шахматной доской, где ходить разрешается только в четыре строны можно воспользоваться следующей записью:
Реализации работ с такой структурой оставляется читателю ![]() Скажу только что граничные клетки, не будут иметь ссылок или вниз (Down=Nil), или вверх (Up=Nil), влево (left=Nil), вправо (Right=Nil). А четыре клетки не будут иметь сразу по две ссылки (Down=Nil,Left=Nil; Down=Nil,Reght=Nil; и т д). Уффф. ну вот и усё. PS: просьба проверить на ошибки (синтаксические, руского языка моего) ![]() Надеюсь, что помог Добавлено @ 19:36
Fedor! обрати внимание! Я же говорил, что было там продолжение, просто когда я редактировал первый свой вариант, то в последний раз случился у меня снова дисконект, и вот результат. как впрочем и сейчас, видишь, полслова отрезало! ![]() -------------------- животное = зверь законченный гентушник |
||||||
|
|||||||
Fedor |
|
|||
![]() Днепрянин ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 2090 Регистрация: 8.2.2003 Где: Великий Репутация: нет Всего: 32 |
-------------------- Мы - Днепряне. Мы всех сильней. |
|||
|
||||
![]() ![]() ![]() |
Правила форума "Delphi" | |
|
Запрещается! 1. Обсуждать и делится взломанными компонентами или программным обеспечением 2. Публиковать ссылки на варез 3. Оффтопить
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, THandle, Rrader, volvo877. |
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | Object Pascal: кроссплатформенные технологии | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |