Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Основы программирования на языке Turbo Prolog.doc
Скачиваний:
56
Добавлен:
09.11.2019
Размер:
563.2 Кб
Скачать

4. Быстрая сортировка_1

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

Итак, необходимо:

1. Разбить L на два списка L1 и L2 примерно одинаковой длины.

2. Отсортировать их, получив списки S1 и S2.

3. Слить отсортированные S1 и S2, получив отсортированный список S.

Рекурсивное правило сортировки supersort1 будет выглядеть так:

supersort1(L,S):-

% разделение на два равных списка

div2(L,L1,L2),

supersort1(L1,S1),

supersort1(L2,S2),

% соединение отсортированных списков

concsort (S1,S2,S).

Определим, что в этой сортировке будет являться граничным условием, то есть задачей, решаемой непосредственно. Список [X], состоящий из одного элемента, правило div2 разделит на два: пустой [] и одноэлементный [X].

Следовательно, у нашей сортировки будут два граничных условия:

supersort1([],[]).

supersort1([X],[X]).

Опишем процедуру div2.

Идея очень простая:

1. Первый элемент списка [X,Y|T] отправляется в список L1, второй — в список L2.

2. Вызывается div2 для хвоста T.

div2([],[],[]).

div2([X],[X],[]).

div2([X,Y|L],[X|L1],[Y|L2]):-

div2(L,L1,L2).

Остается описать процедуру concsort(S1,S2,S) слияния двух отсортированных списков S1 и S2 в отсортированный список S.

Идея следующая:

1. Сравниваются головы H1 и H2 исходных списков. Меньший из этих элементов становится головой целевого списка S.

2. Остатки исходных списков с помощью concsort соединяются в хвост целевого.

concsort([H1|T1],[H2|T2],[H1|T]):-

H1<=H2,!,

concsort(T1,[H2|T2],T).

concsort([H1|T1],[H2|T2],[H2|T]):-

concsort([H1|T1],T2,T).

Так как мы заранее не знаем, какой из списков L1, L2 кончится раньше, то необходимо иметь два граничных условия:

concsort([],L,L).

concsort(L,[],L).

/* Программа 7.3 «очень быстрая сортировка». */

domains

list=integer*

predicates

% очень быстрая сортировка

supersort1(list,list)

% разделение на два примерно равных списка

div2(list,list,list)

% соединение двух отсортированных списков

concsort(list,list,list)

goal

supersort1([1,7,95,1,9,3],L),write(L),nl.

clauses

supersort1([],[]).

supersort1([X],[X]).

supersort1(L,S):-

div2(L,L1,L2),

supersort1(L1,S1),

supersort1(L2,S2),

concsort(S1,S2,S).

div2([],[],[]).

div2([X],[X],[]).

div2([X,Y|L],[X|L1],[Y|L2]):-

div2(L,L1,L2).

concsort([],L,L).

concsort(L,[],L).

concsort([H1|T1],[H2|T2],[H1|T]):-

H1<=H2,!,

concsort(T1,[H2|T2],T).

concsort([H1|T1],[H2|T2],[H2|T]):-

concsort([H1|T1],T2,T).

/* Конец программы */

Упражнение 7.1.

Напишите сортировку методом «пузырька», согласно следующему алгоритму:

% рекурсивное правило bubble:

1. Переставляем первую неупорядоченную пару элементов.

2. Сортируем пузырьком получившийся переставленный список.

% граничное условие bubble:

3. Если такой пары нет (процедура перестановки change дала отказ), значит, исходный список уже отсортирован.

Перестановку двух элементов списка осуществит рекурсивная процедура change:

1. Если первые два элемента списка неупорядочены, то переставляем их.

2. Иначе пропускаем первый элемент и вызываем change для хвоста списка.