Die Umkehrung einer Liste in Prolog
Ich habe fertig, eine Hausaufgabe für meine Programmierung Klasse. Ich sollte erstellen Sie ein Prolog-Programm, das kehrt eine Liste. Ich bin jedoch Probleme zu verstehen, warum genau es funktioniert.
%1. reverse a list
%[a,b,c]->[c,b,a]
%reverse(list, rev_List).
reverse([],[]). %reverse of empty is empty - base case
reverse([H|T], RevList):-
reverse(T, RevT), conc(RevT, [H], RevList). %concatenation
Was genau ist RevT in diesem Fall? Ich weiß es darstellen soll, das Gegenteil von T oder den rest der gegebenen Liste, aber ich weiß nicht, wie es könnte jeder beliebige Wert, da ich noch nicht zugewiesen, es nichts. Sie tut nur dem gleichen Zweck dienen wie RevList aber für jeden rekursiven Aufruf?
Auch, warum ich [H] statt nur H in meinem conc () - Funktion aufrufen? Nicht H beziehen sich auf den Kopf der Liste (ex: [H])? Oder ist es einfach beziehen sich auf das Element am Kopf der Liste (nur H)?
Hilfe bitte deaktivieren Sie dieses, für mich. Ich habe Schwierigkeiten zu verstehen, die Logik hinter dieser Art der Programmierung.
- hilfreiche links: learnprolognow.org/... und csupomona.edu/~jrfisher/www/prolog_tutorial/2_7.html
- Ich begann auch die Umsetzung meiner eigenen Rückseite/2 mit dem Prolog 🙂
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ihre Lösung erklärt:
Wenn wir Umgekehrt die leere Liste, erhalten wir die leere Liste.
Bei Umkehrung die Liste [H|T] , den wir am Ende mit der Liste gewonnen durch Umkehrung T und die Verkettung mit [H] .
Zu sehen, dass die recursive-Klausel korrekt ist, sollten Sie die Liste [a,b,c,d] . Wenn wir rückwärts den Schwanz der Liste, die wir erhalten, [d,c,b] . Verketten dieses mit [a] ergibt sich [d,c,b,a] , die ist die umkehrfunktion von [a,b,c,d]
Anderen reverse Lösung:
nennen:
Für weitere Informationen Lesen Sie bitte: http://www.learnprolognow.org/lpnpage.php?pagetype=html&pageid=lpn-htmlse25
Prolog-Listen sind einfache Datenstrukturen:
./2
[]
.[a]
ist eigentlich dieser Struktur:.(a,[])
.[a,b]
ist eigentlich diese Struktur:.(a,.(b,[]))
[a,b,c]
ist eigentlich diese Struktur:.(a,.(b,.(c,[])))
Die eckige Klammer notation ist syntaktischen Zucker ersparen Sie verbringen Ihr Leben Klammern eingeben. Nicht zu vergessen, dass es einfacher auf die Augen.
Aus dieser erhalten wir den Begriff der Kopf von der Liste (das datum in der äußersten
./2
Struktur) und die Schwanz der Liste (Teilliste enthaltenen äußersten./2
Datenstruktur.Dies ist im wesentlichen, die gleiche Daten-Struktur, die Sie sehen, für eine klassische einfach-verkettete Liste in C:
wo die
next
Zeiger ist entweder NULL oder eine andere Verzeichnis-Struktur.So, dass wir die einfachen [naiv] Umsetzung von reverse/2:
Diese gleichen Algorithmus für die Umkehrung eine einfach-verkettete Liste in eine konventionelle Programmiersprache.
Dieser Algorithmus ist jedoch nicht sehr effizient: es weist O(n2) Verhalten, für den Anfang. Es ist auch nicht tail-rekursiv, was bedeutet, dass eine Liste von ausreichender Länge bewirkt, dass ein stack-überlauf.
Sollte man beachten, dass zum Anhängen eines Elements an eine prolog-Liste erfordert das Durchlaufen der gesamten Liste, voranstellt, ist eine triviale operation, aufgrund der Struktur eines prolog-Liste. Wir können das anfügen eines Elements an eine bestehende Liste so einfach wie:
Einem gemeinsamen idiom in prolog ist die Verwendung eines Arbeiter Prädikat mit einer Akku. Dies macht die
reverse/2
Umsetzung sehr viel effizienter und (vielleicht) ein wenig leichter zu verstehen. Hier kehren wir die Liste durch setzen unsere Akkumulator, wie eine leere Liste. Wir iterieren über die Liste "Quelle". Wie begegnen wir Element in der Liste Quelle die wir voranzustellen, um die umgekehrte Liste, wodurch die umgekehrte Liste, wie wir gehen.Jetzt haben Sie eine
reverse/2
Umsetzung läuft in O(n) Zeit. Es ist auch tail-rekursiv, was bedeutet, dass es kann eine Liste von beliebiger Länge, ohne Blasen seinen stack.Erwägen Sie die Verwendung einer DCG statt, die ist viel einfacher zu verstehen:
Beispiel:
reverse([a,b,c],Q]
aber! nicht-Terminierung mitreverse(P,[a,b,c])
Variablen in Prolog sind 'Platzhalter' für die Beziehungen' Argumente. Was wir wissen, nach einem erfolgreichen Aufruf ist es genau, dass die angegebenen Argumente halten Sie für , dass Beziehung.
Dann
RevT
einen Wert haben wird, wenn der Aufruf erfolgreich ist. Insbesondere das Letzte argument des Aufrufsconc(RevT, [H], RevList)
, wenn die Liste ist nicht leer. Andernfalls wird die leere Liste.Ja, H bezieht sich auf die erste Element (in der Regel genannt element) von der Liste, dann müssen wir 'Umformen', dass es eine Liste (nur 1 element), wie erforderlich, durch conc/3, das ist ein ganz anderes Verhältnis zu Listen.
Nur ein Hinweis auf testen
reverse/2
Prädikat Definitionen, zu lang und passt einen Kommentar.Umkehrung einer Liste ist die "Hallo Welt" - Beispiel für die Einführung von QuickCheck, was bedeutet, dass Sie können es verwenden, für die Unterstützung bei der Prüfung Ihrer definition. Zunächst definieren wir eine Eigenschaft das gilt für die
reverse/2
Prädikat: umdrehen einer Liste zweimal geben müssen, die auf der ursprünglichen Liste, die wir übersetzen:Verwendung von Logtalk ist
lgtunit
tool QuickCheck Umsetzung:Oder einfach:
Aber wir brauchen eine andere Eigenschaft-definition zu testen, mit dem zweiten argument gebunden:
Können wir jetzt tun:
Aber beachten Sie, dass diese Eigenschaft-basiert/randomisierte Tests prüfen nicht für die nicht-terminierende Fällen, da diese nur auftreten, wenn die backtracking nach der ersten Lösung.
Folgenden ist die typische Implementierung von reverse/2 .
Es hat jedoch das problem, wie markiert Balg mit "nicht-Kündigung" .
.
'reverse/2' .
/*
Im folgenden ist eine Implementierung von reverse/2
dass ich nur erfunden, die nicht darunter leiden
aus einer nicht-Kündigung problem für
reverse(P,[])
.*/
'Umsetzung' .
'testen' .
"- Tests : Teil 1' .
"- Tests : Teil 2' .
"Prüfung : Teil 3' .