Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
6d3e0551-6731-11e5-9d50-f6d299da70eeУМК-Пролог.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
469.5 Кб
Скачать

7 Дəріс тақырыбы. Тізімдерді сұрыптау.

Орташа жəне минималды мəнді, тізімдегі элементтердің суммасын табу қарастырылады; тізімдерді іріктеу алгоритмі: көпіршіктік, таңдау , қыстыру , қосылуы , жылдам сұрыптау.

Дəріс конспектісі: Бұл дəрісте элементтері сан болып табылатын тізімдер туралы айтылады. Қарастырылатын көптеген есептерде, тізім элементтері қай доменге жататыны маңызды емес, анық болу үшін оны бүтін сан деп санайық.

Осылайша, біз жұмыс істеуге жоспарланған тізімдерді, домендерді сипаттайтын бөлімде келесідей берілуі мүмкін:

DOMAIN listI= integer* Енді бұдан қызық мəселеге көшейік, анығырақ айтқанда,тізімдерді іріктейік. Іріктеу дегенде элементтердің кейбір тізімде қойылуын түсінеді. Анық болу үшін, тізім элементтерін кему емес бойынша орналастырамыз. Яғни, егер тізімдегі кез-келген жақын екі элементті салыстырсақ, онда келесісі алдынғысынан кіші болмауы керек.

Сортаудың көптеген алгоритмдері бар. Сорттау алгоритмдерінің екі класы бар

екендігін ескерейік: берілгендерді сорттау, ол негізгі есте сақтау жүйесінде орналасқан (внутреняя сортировка), жəне файлдарды сорттау, ол сыртқы сақтау жүйесінде сақталған (внешняя среда). Біз тек ішкі сорттау əдісімен айналысамыз. Ішкі сорттаудың белгілі əдістерін, оларды прологта тізімді сорттау үшін қалай қолдану керектігін қарастырайық жəне анықтайық.

Айтарлықтай белгілі көпіршіктік іріктеу тəсілінен бастайық. Оны тағы тікелей ауыстыру немесе қарапайым ауыстыру əдісі деп атайды.

Көпіршіктік іріктеу

Бұл əдістің ойы келесіге негізделген. Əр бір қадамда тізімдегі көршілес элементтер салыстырылады. Егер олар дұрыс емес тұрса, яғни алдынғы элемент келесіден кіші болса, онда олар орындарымен ауысады. Бұл процесті көршілес, дұрыс емес тізімде орналасқан элементтердің пары балғанға дейін созылады. Ол тізімнің іріктелгенін көрсетеді.

Көпіршікпен аналогия болған себебі, өйткені əр бір минималды элемент тізім басына шығады.

Көпіршіктік іріктеуді екі предикат арқылы жүзеге асырамыз. Олардың біріеуін permutation деп атайық, тізімнің бірінші екі элементтерін салыстырады, егер біріншісі екінші элементтен үлкен болса, онда олардың орындарын ауыстырамыз. Ал егер бірінші жұп дұрыс тізімде орналасса, ол предикат соңын қарастыруға көшеді.

Көмекші предикатты permutation пайдалана отырып, негізгі предикат bubble сізімдегі көпіршіктік іріктеуді жүзеге асырады.

permutation([X,Y􀀀T],[Y,X􀀀T]:Х>У,!.

/* Егер бірінші екіншіден үлкен болса, бірінші екі элементтердің орнын ауыстырамыз

*/

permutation ([X ,T],[X􀀀Tl ]):-

permutation (Т, Т 1 ).

/*соңындағы орын ауыстыруларға көшейік*/

bubble(L,Ll):-

permutation (L,LL), /* орын ауыстыруды жүзеге асыратын предикатты шақырайық * /

bubble(LL,L!). /* алынған тізімді қайта іріктеуге тырысайық */

bubble(L,L). /* егер орын ауыстырулар болмаса, тізім сортталмағанын көрсетеді. * /

Бірақ біздің көпіршіктік əдіс тек дұрыс емес тізбекте орналасқан, ең болмағанда тізімнің бір жұбы болғанша жұмыс істейді. Ондай элементтер біткеннен кейін permutation предикаты сəтсіздікке ұшырайды, ал bubble ережеден фактке өтеді жəне сұрыптаумен тізімді екінші аргументтің сапалы түріне қайтарады.

Қыстыру арқылы сұрыптау

Енді қыстыру сұрыптауын қарастырайық. Ол, егер тізім соңы сұрыпталған болса, онда тізімдегі бірінші элементті оның соңыдағы орнына қою жеткілікті жəне барлық тізім сұрыпталған болып шығады. Бұл ойды жүзеге асыру үшін екі предикат құрайық. Iinsert предикатының мəні – сұрыпталған тізімге ол реттелген күйде қалатындай мəнін қою. Оның бірінші аргументі қоспалы мəн болады, екіншісі - сұрыпталған тізім, үшіншісі-тізім, бірінші аргументтің қойылымы керек жерде екінші аргументтің реті өзгермейтіндей алынған.

ins_sort([ ],[ ]). /* сұрыпталған бос тізім - бос тізім болып қалады. * /

ins _sort([HIT],L):-

ins _ sort(T, Т _ Sort),

/* Т – алғашқы тізімнің соңы,

Т _ Sort – сұрыпталған алғашқы тізімнің соңы * /

inse~l·1-T.T _ Sort,L).

Н қоямыз (алғашқы тізімнің бірінші элементі) T_Sort, L аламыз (тізім , алғашқы тізімнің элементтерінен тұратын жəне кему бойынша емес тұрғандар.) */

insert(X,[],[X]). /* бос тізімге кез-келген мəнді қойсақ, бір элементті тізім аламыз. */

insert(X, [H􀀀T], [H􀀀Tl ]):-

Х>Н,!, /* егер қойылатын мəн тізімнің басынан үлкен болса, онда оны соңына қою керек. * /

insert(X,T,Tl).

/*Х-ті Т-нің соңына қойамыз, нəтижесі Т1 тізімін аламыз */

insert(X,T,[XI 1) ./*бұл ұсыныс егер қойылатын мəн Т тізімінің басынан үлкен болмаса, онда оны Т тізіміне бірінші элемент деп қояғанда ғана қоямыз. */

Таңдау арқылы сұрыптаймыз.

Алгоритм ойы таңдау арқылы сұрыптау өте қарапайым. Тізімде минималды элементті табамыз (осы лекция басында ойлап тапқан предикатты min_list пайдалана отырып). Оны тізімнен жоямыз (алдынғы лекцияда қарастырылған, delete _ one предикат көмегімен).

Қалған тізімді сұрыптаймыз. Сұрыпталған тізімге басы ретінде минималды элементті қосамыз. Себебі бұл элемент алғашқы тізімдегі барлық элементтерден кіші болды, жəне ол сұрыталған тізімнің барлық элементтерінен кіші болады.Жəне соған байланысты, егер оны тізімді сорттау басына қойсақ, онда тізбек өзгермейді:

Жазып алайық:

choice([ ],[ ]). /* сұрыпталған бос тізім - бос тізім болып қалады. * /

choice(L,[XIT]):- /* Х-ті сұрыпталған тізімге Т жазамыз.

(L-тізімінің минималды элементі) */

min _list(L,X), /* Х - L-тізімінің минималды элементі */

delete _ one(X,L,L 1),

/* L 1 - L тізімінен Х элементінің бірінші кірісінің нəтижесін өшіру * /

choi r(L 1, Т). /* L 1 тізімін сұрыптайық,

нəтижесін Т – деп белгілейік* /

Тез сұрыптау

“Тез сорттаудың” авторы Хоар болып табылады. Ол оны тез деп атады, өйткені жалпыжағдайда бұл алгоритмнің эффектілігі айтарлықтай жоғары. Əдіс ойы келесідей. Алғашқы тізімді екі жазылымға бөлеміз, ол кейбір кедергілі элемент қолданылады. Біріншісінде__________кедергі элементінен кіші элементті орналастырамыз, екіншісінде – үлкен не тең. Бұл тізімдердің əр қайсысын сол əдіспен сұрыптаймыз, одан кейін тізімге кедергіден кіші элементтерді қосамыз, ең бірінші кедергі элементтің өзін, одан кейін кедергіден кіші элементтердің тізімін. Нəтижесінде дұрыс тізімде тұрған элементтерден тұратын тізімді аламыз.

Бұл ойды программалық кодқа іске асыру үшін, бізге қарапайым предикат керек болады.

Рartition қосымша предикаты екі қосымша тізімшеге бөлінуіне жауапшы болады. Онда төрт аргумент болады. Бірінші екі элемент -енетін: біріншісі – алғашқы тізім, екіншісі –кедергілік элемент. Үшінші жəне төртінші элементтер –шығатын, соған байланысты кедергіден кіші алғашқы тізімнің элементтер тізімі, жəне кедергі элементтерінен кіші емес элементтерден тұратын тізім. Quick_sort предикаты Хоардың тез сұрыптау алгоритмымен жүзеге асырылады. Ол екі сөйлемнен құралатын болады. Мынаны жазып алайық:

quick_sort([],[]). /* Сортталған бос тізім бос болып қалады. */ quick_sort([H􀀀T],C):-

partiton( T,H,L,G),

Т тізімін L(Н барьерлі элементінен кіші элементтер тізімі) жəне G (Н-тан кіші емес

элементтер тізіміне) тізімді бөлеміз. * /

quick _ sort(L,L _ s),

/* L_s тізімі – L тізімінің элементтерін реттеу нəтижесі */

quick. _sort(G,G _s),

Аналогты, G~s тізімі – G тізімдегі элементтердің реттелу нəтижесі. * /

conc(L _s,[H􀀀G._s],O).

/* L_s тізімдерінің басы Н тізімімен қосылуы, ал G_s соңы. Нəтижесін О деп

белгілейміз * / .

partition([],_,[],[]). /* бос тізімдердің элементтерін қалай бөлсекте, бос тізімнен босқа еш

нəрсе алмаймыз*/

partition([XIT] Y,[X􀀀T1 ],Bs):-

Х<У,!,

partition(T,Y,Tl,Bs).

/* егер Х элементі У кедергі элементінен кіші болса, онда оның үшінші аргументін

қосамыз. * /

partition([X􀀀T У,Т1 ,[X􀀀Bs ]):-

раrtition(Т, У, Тl ,Bs).

/* кері жағдайда оны төртінші аргументке жазамыз * /

Сұрттаудың келесі алгоритмін зерттеуге көшпей жатып, бір қосалқы есепті шығарайық.

Бізде реттелген екі тізім бар болсын, жəне біз олардың элементтерін қосылған тізім-сұртталған түрде қалатындай етіп олардың элементтерін қосқымыз.

Предикатты жүзеге асыру ойы , екі сортталған тізімнің тəртіпті сақтауымен қосуды орындауы айтарлықтай қарапайым. Əр қадамда реттелген тізімдердің бастарын салыстырып отырамыз, онда ең кішісін салдарлы тізімге көшіреміз. Солай тізімдердің бірі біткенше қыламыз. Тізімдердің біреуі босағанда, бос емес тізімдегі қалдықты жазу қалады. Нəтижесінде алғашқы екі тізімнен тұратын тізім аламыз,;, Жəне олардың элементтерінін орналасуы керек орында. Берілген сипаттаманы жүзеге асыратын предикат құрайық (оны fusion деп атайық). Тізімдердің қайсысы бірінші босайтынын білменгеннен кейін, бізге рекурсияны екі базалық тізім бойынша қуу керек. Бізде екі факт болады – рекурсия негізі егер біз кейбір тізімді бос тізіммен қоссақ, онда біз нəтижелінде сол тізімді аламыз. Бірінші тізім бос кезінде жəне екінші тізім бос кезінде бұл факт орын алады. Рекурсия қадамын екі ереже береді: біріншісі - егер бірінші тізімнің басы екінші тізімнің басынан кіші болса, онда дəл бірінші тізім басын салдарлайтын тізім ретінде жазу керек, одан кейін бірінші тізім соңының екіншісімен қосылуына көшу керек. Бұл қосылудың нəтижесі ақырғы тізімнің соңы болып келеді. Екінші ереже керісінше, салдарлы тізім басы ретінде екінші тізімнің басын толықтырып отырады жəне бірінші тізімді екінші тізім соңымен қосады.

fusion(Ll,[ ],Ll):-! /* Ll тізімі бос тізіммен

қосқанда L 1 тізімін аламыз * /

fusion([ ],L2,l '):-/* L2 тізімі бос тізіммен қосқанда

L2 тізімін аламыз * /

fusion([H1􀀀T1],[H2􀀀T2],[H1􀀀T]):- Н1<Н2,!,

/* егер Нl бірінші Н2 тізімнің басынан кіші болса /

fusion(T1, [Н2􀀀Т2],Т).

/* бірінші тізімнің Т1 аяқ жағын екінші тізіммен қосамыз [Н2􀀀Т2] * /

fusion(L1, [Н2􀀀T2],[Н2􀀀Т]):-

fusion(L1,Т2,Т).

/ L 1 бірінші тізімді Т2 екінші тізім соңымен қосамыз * /

Енді қосу арқылы сорттау алгоритмін анықтауға көшуге болады.

Қосу арқылы сұрыптау

Қосылу əдісі – “ежелгі” сұрыптардың алгоримдерінің бірі. 1945 жылы Джон фон

Нейман ойлап тапқан. Бұл ой келесіде негізделген. Екі тізімге реттеу үшін тізімді бөлеміз.

Осы элементтердің əр-қайсысын сол əдіспен реттейік, одан кейін реттелген тізімшелерді қайта ортақ бір тізімге қосамыз. Алғашқы тізімді екіге бөлетін, бірінші предикат құраймыз. Ол екі факттен жəне ережелерден тұратын болады. Бірінші факт бос тізімді екі бос тізімге болады деп тұжырымдайды. Екінші факт бір элементті тізімнің сол бір элементті тізімге жəне бос тізімге бөлінуін тұжырымдайды.

splitting([],[],[])./* бос тізімді тек бос тізімшелерге бөлуге болады * /

sрlittiпg([Н],[Н],Ш. /* бір элементті тізімді тек бір элементті тізімге бөлуге болады * /

splitting([H1 ,Н2􀀀Т],[Н1􀀀Т1 ],[Н2􀀀Т2]):-

splitting(T,Tl,T2).

/* Н1 элементті бірінші тізімшеге жібереміз, Н2 элементті – екінші тізімшеге жібереміз,

Т арт жағын Т1 жəне Т2 тізімшелерге бөлеміз.*/

Енді негізгі предикатты жазуға кірісуге болады жəне ол тізімді сорттауды жүзеге асырады. Ол үш ұсыныстан тұратын болады. Біріншісі анық фактті деклорациялайды. Бос тізімді сұрыптағанда, бос тізім шығады. Екіншісінде бір элементті тізім реттелген болып келеді дейді. Үшінші ережеде қосылу сұрыптаудың əдісінің мəні бар. Басында splitting предикатының көмегімен тізімшелер екіге бөлінеді, содан олардың əр-қайсысы fusion sort предикаты рекурсивті шақырумен сұрыпталады, жəне, соңында, fusion предикатын қолдану арқылы, алынған реттелген тізімшелерді бір тізімге қосамыз, жəне ол алғашқы тізім элементтерінің реттелу нəтижесі болып табылады. Бастағы түсініктің баяндамасын жазайық.

fusion_soгt([],[]):-!./* сортталған бос тізім бос болып қалады.

fusion soгt([H] [H]):-I. /* бірэлементті тізім реттелген*/

fusiоп_sоrt(L,L _s):-

splitting(L,L 1 ,L2),

/* L тізімін екі тізімшеге бөлеміз. * /

fusion _sort(Ll,Ll_s), /*

Ll_s - Ll сұрыптарын жүзеге асырады.*/

fusion sortCТ~2,L2 s),

/* L2_s - L2 сұрыптарын жүзеге асырады. */

fusion(L 1_ s,L2 _ s,L _s).

/* L s тізіміне Ll s и L2 s қосамыз */

Келесі этапта екі элементті тізімдер т.б. қосылады. Соңғы қадамда екі тізімше

қосылады: нəтижелі, сұрыпталған.

Сұрыптау тақырыбын аяқтамасы ретінде, тізімнің реттелгендігендігін тексеретін предикатты өңдейік. Ол тіпті де қиын емес. Тізім реттелген болу үшін, ол немесе бос болуы керек, немесе бір элементті болуы керек, немесе кез-келген жақын элементтер дұрыс тізбекте болуы керек. Осы талқымаларды жазайық.

sorted([ ]). /* сұрыпталған бос тізім

* / sorted([_])./* бір элементті тізім реттелген * /

sorted( [Х, YI Т]):-

Х<=У, sorted([Y[T]).

/* тізім реттелген, егер бірінші екі элемент дұрыс тізімде орналасса жəне екінші элементпен тізім құрылса * /

Орташа жəне минималды мəнді тізімдегі элементтердің суммасын табу

қарастырылады;тізімдерді сұрыптау əдістері: көпіршіктік, таңдау арқылы , қыстыру арқылы, жылдам сорттау.

Негізгі əдебиет 1 [120-138]

Қосымша əдебиет 3 [15-29]

Бақылау сұрақтары:

1.Тізімдерді сұрыптау алгоритмдері- пузырьковый.

2.Тізімдерді сұрыптаутау алгоритмдері - таңдау арқылы

3.Тізімдерді сұрыптау алгоритмдері- қыстыру арқылы.

4.Тізімдерді сұрыптау алгоритмдері- бірігу арқылы.

5.Тізімдерді сұрыптау алгоритмдері – жылдам сорттау.__

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]