Чтение онлайн

на главную - закладки

Жанры

Программирование на языке Ruby
Шрифт:

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

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

больший диск на меньший.

В следующем примере приведено решение этой задачи с использованием стека. Мы ограничились тремя дисками, потому что для перемещения 64 компьютеру потребовались бы века.

def towers(list)

 while !list.empty?

n, src, dst, aux = list.pop

if n == 1

puts "Перемещаем диск с #{src} на #{dst}"

else

list.push [n-1, aux, dst, src]

list.push [1, src, dst, aux]

list.push [n-1, src, aux, dst]

end

 end

end

list = []

list.push([3, "a", "c", "b"])

towers(list)

Вот что напечатает эта программа:

Перемещаем диск с а на с

Перемещаем диск с а на b

Перемещаем диск с с на b

Перемещаем диск с а на с

Перемещаем диск с b на а

Перемещаем диск с b на с

Перемещаем диск с а на с

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

def towers(n, src, dst, aux)

 if n==1

puts "Перемещаем диск с #{src} на #{dst}"

 else

towers(n-1, src, aux, dst)

towers(1, src, dst, aux)

towers(n-1, aux, dst, src)

 end

end

towers(3, "а", "с", "b")

Печатается точно такой же результат. Возможно, вам будет интересно знать, что «закомментарили» предложения, осуществляющие вывод, и сравнили время работы. Никому не говорите, но рекурсивное решение оказалось в два раза быстрее!

9.2.4. Более строгая реализация очереди

Мы определим очередь примерно так же, как стек. Если вы хотите защититься от некорректного доступа к структуре данных, рекомендуем поступать аналогично.

class Queue

 def initialize

@store = []

 end

 def enqueue(x)

@store << x

 end

 def dequeue

@store,shift

 end

 def peek

@store.first

 end

 def length

@store.length

 end

 def empty?

@store.empty?

 end

end

Отметим,

что класс
Queue
имеется в библиотеке
thread
для поддержки многопоточных программ. Имеется даже вариант
SizedQueue
для организации очереди ограниченного размера.

В упомянутых классах методы имеют короткие имена:

enq
и
deq
. У них есть также синонимы
push
и
pop
, что лично мне кажется неоправданным. Это структура данных FIFO, а не LIFO, то есть именно очередь, а не стек.

Разумеется, класс

Queue
в библиотеке
thread.rb
безопасен относительно потоков. Если вы хотите реализовать такой же класс
Stack
, рекомендую взять
Queue
в качестве отправной точки. Потребуется внести не так много изменений.

В первом издании книги был длинный пример, демонстрирующий работу с очередями. Но, как и некоторые примеры, касающиеся стеков, он был исключен ради экономии места.

9.3. Деревья

Я не увижу никогда, наверное, Поэму столь прекрасную как дерево. Джойс Килмер, «Деревья» [11]

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

11

Пер. Я. Фельдмана. — Прим. ред.

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

Поделиться:
Популярные книги

Старый тракт (сборник)

Марков Георгий Мокеевич
Сибириада
Проза:
современная проза
7.12
рейтинг книги
Старый тракт (сборник)

Кодекс Охотника. Книга XII

Винокуров Юрий
12. Кодекс Охотника
Фантастика:
боевая фантастика
городское фэнтези
аниме
7.50
рейтинг книги
Кодекс Охотника. Книга XII

Хроники Перна: Первое Падение

Маккефри Энн
2. Всадники Перна: Предыстория
Фантастика:
эпическая фантастика
9.00
рейтинг книги
Хроники Перна: Первое Падение

Табак

Димов Димитр
Проза:
историческая проза
6.25
рейтинг книги
Табак

Молния Баязида

Посняков Андрей
4. Русич
Фантастика:
альтернативная история
7.70
рейтинг книги
Молния Баязида

Отморозок 4

Поповский Андрей Владимирович
4. Отморозок
Фантастика:
попаданцы
фантастика: прочее
5.00
рейтинг книги
Отморозок 4

Летописи Святых земель

Копылова Полина
Фантастика:
фэнтези
6.25
рейтинг книги
Летописи Святых земель

Дом в овраге

Варго Александр
MYST. Черная книга 18+
Детективы:
триллеры
9.14
рейтинг книги
Дом в овраге

Т. 13 Число зверя

Хайнлайн Роберт Энсон
13. Отцы-основатели. Весь Хайнлайн
Фантастика:
научная фантастика
7.00
рейтинг книги
Т. 13 Число зверя

Мелодия души

Бэлоу Мэри
2. Марлоу и Кендрик
Любовные романы:
исторические любовные романы
8.30
рейтинг книги
Мелодия души

Телзи Амбердон

Шмиц Джеймс Генри
The Federation Of The Hub
Фантастика:
научная фантастика
5.00
рейтинг книги
Телзи Амбердон

Один против всех

Сухов Евгений Евгеньевич
Детективы:
боевики
7.67
рейтинг книги
Один против всех

Свидетель

Герритсен Тесс
Детективы:
триллеры
8.17
рейтинг книги
Свидетель

Чужак

Листратов Валерий
1. Ушедший Род
Фантастика:
попаданцы
аниме
фэнтези
5.25
рейтинг книги
Чужак