- •Оглавление
- •Логическое программирование. Язык Prolog.
- •1. Предикаты Пример 1.1. Максимум из двух чисел
- •Пример 5.2. Вычисление факториала
- •6. Хвостовая рекурсия Пример 6.1. Вычиление факториала с с использованием хвостовой рекурсии
- •Пример 6.2. Вычисление чисел Фибоначчи
- •Пример 7.4. Обращение списка
- •Пример 7.5. Среднее арифметическое элементов списка.
- •7. Обработка списков Пример 7.1. Вычисление длины списка
- •Пример 7.2. Проверка принадлежности элемента списку
- •Пример 7.3. Соединение двух списков
- •8. Сортировка списков Пример 8.1. Пузырьковая сортировка
- •Пример 8.2. Сортировка вставкой
- •Пример 8.3. Сортировка выбором
- •9. Строки
- •Пример 9.3. Преобразование строки в список символов
- •Пример 9.4. Подсчет кол-ва вхождений заданного символа в строку
- •Пример 9.6. Замена заданного символа в строке – на другой
- •Пример 9.7. Удаление части строки
- •Пример 9.8. Копирование части строки
- •Пример 9.9. Вставка одной строки внутрь другой
- •10. Множества Пример 10.1. Превращение произвольного списка в множество
- •Пример 10.2. Операция объединения двух множеств.
- •Пример 10.3. Пересечение множеств
- •Пример 10.4. Разность множеств
- •Пример 10.5. Проверка, является ли одно множество подмножеством другого.
- •Пример 10.6. Предикат, реализующий отношение равенства двух множеств.
- •Пример 10.7. Определение собственного подмножества множества
- •Пример 10.8. Симметричная разность
- •Пример 10.9. Дополнение множества
- •11. Деревья Пример 11.1. Принадлежность элемента дереву
- •Пример 11.2. Замена заданного значения на другое в дереве
- •Пример 11.3. Подсчет общего количества вершин дерева
- •Пример 11.4. Подсчет количества листьев (узлов без сыновей)
- •Пример 11.5. Подсчет суммы чисел в вершинах дерева
- •Пример 11.6. Предикат, вычисляющий высоту дерева
- •Пример 11.7. Проверка принадлежности значения двоичному справочнику .
- •Пример 11.8. Добавление элемента в двоичный справочник
- •Пример 11.9. Генератор случайного двоичного справочника из чисел
- •Пример 11.10. Удаление заданного значения из двоичного справочника
- •Пример 11.11. Преобразование произвольного списка в двоичный справочник
- •Пример 11.12. Предикат, сворачивающий заданный двоичный справочник в список
- •12. Базы знаний Пример 12.1. Вычисление чисел Фибоначчи с запоминанием результатов
- •13. Логические задачи (головоломки) Пример 13.1. Перестановка кубиков
- •Пример 13.2. Ханойский башни
- •Пример 13.3. Волк, коза и капуста
- •Пример 13.4. Побег из Зурга
8. Сортировка списков Пример 8.1. Пузырьковая сортировка
Идея этого метода заключается в следующем. На каждом шаге сравниваются два соседних элемента списка. Если оказывается, что они стоят неправильно, то есть предыдущий элемент меньше следующего, то они меняются местами. Этот процесс продолжаем до тех пор, пока есть пары соседних элементов, расположенные в неправильном порядке. Это и будет означать, что список отсортирован.
Реализуем пузырьковую сортировку посредством двух предикатов. Один из них, назовем его permutation, будет сравнивать два первых элемента списка и в случае, если первый окажется больше второго, менять их местами. Если же первая пара расположена в правильном порядке, этот предикат будет переходить к рассмотрению хвоста.
Основной предикат bubble будет осуществлять пузырьковую сортировку списка, используя вспомогательный предикат permutation.
/* переставляем первые два элемента, если первый больше второго */
permutation([X,Y|T],[Y,X|T]):- X>Y,!.
/*переходим к перестановкам в хвосте*/
permutation([X|T],[X|T1]):- permutation(T,T1).
/* вызываем предикат, осуществляющий перестановку */
bubble(L,L1):-
permutation(L,LL),
!, bubble(LL,L1). /* пытаемся еще раз отсортировать полученный список */
bubble(L,L). /* если перестановок не было, значит список отсортирован */
Но наш пузырьковый метод работает только до тех пор, пока есть хотя бы пара элементов списка, расположенных в неправильном порядке. Как только такие элементы закончились, предикат permutation терпит неудачу, а bubble переходит от правила к факту и возвращает в качестве второго аргумента отсортированный список.
Пример 8.2. Сортировка вставкой
Теперь рассмотрим сортировку вставкой. Она основана на том, что если хвост списка уже отсортирован, то достаточно поставить первый элемент списка на его место в хвосте, и весь список будет отсортирован. При реализации этой идеи создадим два предиката.
Задача предиката insert — вставить значение (голову исходного списка) в уже отсортированный список (хвост исходного списка), так чтобы он остался упорядоченным. Его первым аргументом будет вставляемое значение, вторым — отсортированный список, третьим — список, полученный вставкой первого аргумента в нужное место второго аргумента так, чтобы не нарушить порядок.
Предикат ins_sort, собственно, и будет организовывать сортировку исходного списка методом вставок. В качестве первого аргумента ему дают произвольный список, который нужно отсортировать. Вторым аргументом он возвращает список, состоящий из элементов исходного списка, стоящих в правильном порядке.
/* отсортированный пустой список остается пустым списком */
ins_sort([ ],[ ]).
/* T — хвост исходного списка,T_Sort — отсортированный хвост исходного списка */
ins_sort([H|T],L):- ins_sort(T,T_Sort), insert(H,T_Sort,L).
/* вставляем H (первый элемент исходного списка)в T_Sort, получаем L (список, состоящий из элементов исходного списка, стоящих по неубыванию) */
insert(X,[],[X]).
/* при вставке любого значения в пустой список, получаем одноэлементный список*/
/* если вставляемое значение больше головы списка,
значит его нужно вставлять в хвост */
insert(X,[H|T],[H|T1]):- X>H,!, insert(X,T,T1).
/* вставляем X в хвост T, в результате получаем список T1 */
insert(X,T,[X|T]).
/* это предложение (за счет отсечения в предыдущем правиле) выполняется,
только если вставляемое значение не больше головы списка T, значит,
добавляем его первым элементом в список T */
