Advertisement
exnon

1653

Nov 18th, 2020
2,923
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Erlang 10.40 KB | None | 0 0
  1. %% coding: latin-1
  2. %Quellen:
  3. %http://erlang.org/documentation/doc-5.3/doc/getting_started/getting_started.html
  4. %2.
  5. %https://erlang.org/doc/reference_manual/expressions.html#:~:text=Erlang%20uses%20single%20assignment,%20that,its%20value%20can%20be%20ignored.&text=Variables%20starting%20with%20underscore%20(_),are%20normal%20variables,%20not%20anonymous
  6. %3.
  7. %VL vom 03.11.2020
  8. %4.
  9. %util.erl
  10. -module(btree).
  11. -export([initBT/0,isEmptyBT/1,isBT/1,equalBT/2, insertBT/2, findBT/2, inOrderBT/1, deleteBT/2]).
  12.  
  13. %initBT() erzeugt einen leeren Baum.
  14. %Doku: 2.2 Abbildung 1
  15. %Stelligkeit: 0, Sichtbarkeit: public, Rückgabewert: Tupel
  16.  
  17. initBT() ->
  18.         {}.
  19.  
  20. %isEmptyBT() überpürft ob ein Baum ein leerer Baum ist.
  21. %Doku: 2.2 Abbildung 2
  22. %Stelligkeit: 1, Sichtbarkeit: public, Rückgabewert: bool
  23.  
  24. isEmptyBT(BTree) ->
  25.         BTree == {}.
  26.  
  27. %isBT() überprüft einen Baum auf seine Korrekt nach Definition
  28. %Die einzelnen Constraints für einen korrekten Baum werden im folgenden noch detaillierter beschrieben
  29. %Entwurf: 2.2 Abbildung 3
  30. %Stelligkeit: 1, Sichtbarkeit: public, Rückgabewert: bool
  31.  
  32. %BTree wird um ein Minimum und Maximum erweitert.
  33. isBT(BTree) ->
  34.         isBT(BTree, 0, inf).
  35.  
  36. %Sollte der betrachtete Baum leer sein, spielt das MInimum und Maximum keine weitere Rolle - der Baum ist korrekt.
  37. isBT(_BTree = {}, _Minimum, _Maximum) ->
  38.         true;
  39.  
  40. %Sortierung:
  41.     %Minimum und Maximum bilden nun ein Intervall in dem das Element des übergebenen Baumes liegen darf.
  42. %Die Syntaktische Korrektheit wird überprüft:
  43.     %Ist das Tupel als die richtige Datenstruktur verwendet?
  44.         %Ist das Element eines jeden Teilbaumes vom Typ Ganzzahl (Integer)?
  45. %Ist die Höhe im Baum richtig angegeben?
  46.     %Die richtige Höhe nach Definition (siehe findHeight) wird errechnet und mit der übergebenen Höhe verglichen.
  47. %Rekursiver Aufruf der Teilbäume:
  48. %   Sind die Bedingungen für einen korrekten BST in allen Teilbäumen erfüllt?
  49. isBT(_BTree = {ElementAtom,Height,Leftsub,Rightsub}, Minimum, Maximum) when ElementAtom>Minimum, ElementAtom<Maximum ->
  50.         (util:type_is(ElementAtom) == integer) and
  51.         (findHeight(Leftsub,Rightsub) == Height) and
  52.         isBT(Leftsub, Minimum, ElementAtom) and
  53.         isBT(Rightsub, ElementAtom, Maximum);
  54.  
  55. %Sollte Unsinn als Baum übergeben werden, der nicht der richtigen Datenstruktur folgt, wird false returned.
  56. isBT(_BTree, _Minimum, _Maximum) ->
  57.         false.
  58.  
  59.  
  60.  
  61.  
  62. %Wenn beide Unterbäume leer sind, sind beide leeren Bäume mit Höhe 0 zu interpretieren und 1 wird returned.
  63. findHeight(_Leftsub = {}, _Rightsub = {}) ->
  64.             1;
  65.  
  66. %Sollte nur einer der beiden Unterbäume leer sein, muss dies als Höhe 0 interpretiert werden.
  67. %Der jeweils andere Baum ist also auch ohne Vergleich der "höhere".
  68.  
  69. findHeight(_Leftsub = {_ElementLeft,HeightLeft,_Leftsubsub,_Rightsubsub}, _Rightsub = {}) ->
  70.             HeightLeft + 1;
  71.  
  72. findHeight(_Leftsub = {}, _Rightsub = {_ElementRight,HeightRight,_Leftsubsub,_Rightsubsub}) ->
  73.             HeightRight + 1;
  74.  
  75.  
  76. %Private Hilfsfunktion zum Errechnen der Höhe eines Teilbaumes für die folgende Funktion
  77. %Wenn die Höhe zweier, nicht leerer Unterbäume gefunden werden soll, wird die Höhe der beiden Unterbäume verglichen und der "höhere" wird mit 1 addiert. [nach Definition Höhe (siehe VL)]
  78. findHeight(_Leftsub = {_ElementLeft,LH,_LeftLeftsub,_LeftRightsub}, _Rightsub = {_ElementRight,HeightRight,_RightLeftsub,_RightRightsubsub}) ->
  79.             max(LH, HeightRight) + 1.
  80.  
  81.  
  82. %isEqual überprüft die semantische Gleicheit zweier Bäume.
  83. %Sollte keiner der beiden Bäume leer sein, wird inOrderBT benutzt um die beiden Bäume als sortierte Liste umzuformen
  84. %und im Folgenden auf syntaktische Gleichheit zu überprüfen.
  85. %Doku: 2.2 Abbildung 4
  86. %Stelligkeit: 2, Sichtbarkeit: public, Rückgabewert: bool
  87.  equalBT(BaumEins,BaumZwei) ->
  88.         inOrderBT(BaumEins)==inOrderBT(BaumZwei).
  89.  
  90. %Hilfsmethode für Hoehe
  91. getHoehe({_Zahl, Hoehe, _Liniks, _Rechts}) -> Hoehe;
  92. getHoehe ({}) -> 0.
  93.  
  94.  
  95. %insertBT fügt einen neuen Node dem BTree hinzu und positioniert es an der richtigen stelle
  96. %Stelligkeit: 2, Sichtbarkeit: Public, Rückgabewert: Tupel
  97. %Doku: TODO
  98. insertBT({},Element) ->
  99.     {Element, 1, {}, {}};
  100.  
  101. insertBT(BTree= {Zahl, Hoehe, Links, Rechts}, Element) ->
  102.     BTree = {Zahl, Hoehe, Links, Rechts},
  103.     if Element < Zahl ->
  104.         NeuerLinks = insertBT(Links, Element),
  105.         Hanoi = 1+max(getHoehe(NeuerLinks),getHoehe(Rechts)),
  106.         {Zahl, Hanoi, NeuerLinks, Rechts};
  107.     Element > Zahl ->
  108.         NeuerRechts = insertBT(Rechts,Element),
  109.         Hanoi = 1+max(getHoehe(NeuerRechts),getHoehe(Links)),      
  110.         {Zahl, Hanoi, Links, NeuerRechts};
  111.     true ->
  112.         BTree
  113.     end.
  114.    
  115.  
  116.  
  117. %findBT() wird ein Baum und ein Element übergeben.
  118. %Daraufhin wird das Element im Baum gesucht.
  119. %Falls es im Baum existiert wird die Höhe returned, falls nicht ein Error.
  120. %Entwurf: 2.2 Abbildung 7
  121. %Stelligkeit: 2, Sichtbarkeit: public, Rückgabewert: int
  122. %Wenn der Baum leer ist, kann das Element nicht darin vorkommen und Error (-1) wird returned.
  123. %Das leere Element wird hier ignoriert.
  124.  
  125. findBT({}, _Element) ->
  126.         -1;
  127.  
  128. %BTree Tupel wird zur weiteren Bearbeitung in mehreren Atomen definiert. (ElementAtom = <ELEMENT>, Height = <HÖHE>)
  129. %Das Übergebene Element wird mit dem Element des aktuellen Nodes verglichen
  130. %Sollten die ELement übereinstimmen, wurde das gesuchte Element gefunden und seine Höhe wird returned.
  131. %Falls nicht, werden die beiden Elemente verglichen:
  132. %Ist das gesuchte Element größer als das Element unseres aktuellen Nodes,
  133. %müssen wir im Folgen den im rechten Unterbaum unseres aktuellen Nodes weitersuchen.
  134. %Wenn das gesuchte Element kleiner ist, suchen wir im linken Unterbaum weiter.
  135. %Die Funktion wird erneut mit dem jeweiligen Unterbaum aufgerufen, bis das gesuchte Element gefunden ist oder wir an einem Blatt angekommen sind.
  136. findBT(BTree, Element) ->
  137.         {ElementAtom, Height, Leftsub, Rightsub} = BTree,
  138.             if Element == ElementAtom ->
  139.                 Height;
  140.             Element > ElementAtom ->
  141.                 findBT(Rightsub, Element);
  142.             Element < ElementAtom ->
  143.                 findBT(Leftsub,Element)
  144.             end.
  145.  
  146. %inOrderBT() gibt den Baum in einer aufsteigend sortierten Liste zurück.
  147. %Entwurf: 2.2 Abbildung 8
  148. %Stelligkeit: 1, Sichtbarkeit: public, Rückgabewert: list
  149.  
  150. %Ist der Baum leer wird eine leere Liste returned.
  151. inOrderBT({}) ->
  152.         [];
  153.  
  154. %Ist das aktuelle Node ein Blatt wird das Element des aktuellen Elements in die Liste eingefügt und die Liste wird zurückgegeben.
  155. inOrderBT({ElementAtom,_Height,{},{}}) ->
  156.         [ElementAtom];
  157.  
  158. %Wenn das aktuelle Node nur einen rechten Unterbaum hat, können wir davon ausgehen, dass kein kleineres Element mehr gefunden wir dals das Element in dem aktuellen Node.
  159. %Also wird es in die Liste eingefügt und die Funktion wird nachfolgend mit dem rechten Unterbaum, der auschließlich größere ELemente enthalten wird, aufgerufen.
  160. inOrderBT({ElementAtom,_Height,{},Rightsub}) ->
  161.         [ElementAtom] ++ inOrderBT(Rightsub);
  162. %Falls das aktuelle Node keinen rechten Unterbaum, dafür aber einen linken besitzt, können wir das Element des aktuellen noch nicht in die liste einfügen,
  163. %da sich mit Sicherheit noch ein kleineres Element im Baum befindet.
  164. %Wir müssen also zunächst den linken Unterbaum an inOrderBT übergeben und können danach das Element des aktuellen Nodes in die Liste einfügen.
  165. inOrderBT({ElementAtom,_Height,Leftsub,{}}) ->
  166.         inOrderBT(Leftsub) ++ [ElementAtom];
  167.  
  168. %Im Falle, dass das aktuelle Node sowohl einen linken als auch einen rechten Unterbaum besitzt, müssen wir zunächst den linken Unterbaum an inOrderBT übergeben um die kleineren ELement zu finden.
  169. %Dann können wir das Element des aktuellen Nodes in die Liste einfügen, da es keine kleineren Element mehr im Baum gibt.
  170. %Um sicherzustellen, dass alle Elementen ihren Platz in der sortierten Liste finden, müssen wir anschließend noch den rechten Unterbaum überprüfen.
  171. %Wir rufen nun also noch inOrderBt mit dem rechten Unterbaum auf.
  172. inOrderBT(_BTree ={ElementAtom,_Height,Leftsub,Rightsub}) ->
  173.         inOrderBT(Leftsub) ++ [ElementAtom] ++ inOrderBT(Rightsub).
  174.  
  175. %%Wenn wir einen Leerenbaum als Parameter erhalten, gibt es das gewünschte Element nicht im BTree
  176. deleteBT({}, _Element) -> {};
  177.  
  178. deleteBT(BTree = {ElementAtom,Height,Links,Rechts}, Element) ->
  179.     if %%Wir haben 3 Cases hier:
  180.         %a) Element ist Größer als das ElementAtom vom root, b) es ist kleiner und c) es ist gleich groß
  181.        
  182.         %a) Hier wird "tiefer" im Baum nach dem Element gesucht, anschließend wird die Höhe korrigiert und es wird ein ErsatzKnoten zurückgegeben
  183.         Element > ElementAtom ->
  184.             NeuRechts = deleteBT(Rechts, Element),
  185.             Hanoi = findHeight(NeuRechts, Links),
  186.             {ElementAtom,Hanoi,Links,NeuRechts};
  187.         %b) Hier geschieht das Equivalente für den Linkenbaumteil
  188.         Element < ElementAtom ->    
  189.             NeuLinks = deleteBT(Links, Element),
  190.             Hanoi = findHeight(NeuLinks, Rechts),
  191.             {ElementAtom,Hanoi,NeuLinks,Rechts};
  192.         %c) Hier haben wir unser Element gefunden.
  193.         %Nun wird abgefragt ob das Node nur leere Linke und Rechte Teilbäume hat oder ob es beide hat.
  194.         Element == ElementAtom ->
  195.             if  %Beim Fall dass es nur einen Teilbaum gibt, wird einfach der Linke, bzw. Rechte Teilbaum zurückgegeben.
  196.                 BTree == {ElementAtom, Height, Links,{}} -> Links;
  197.                
  198.                 BTree == {ElementAtom, Height, {},Rechts} -> Rechts;
  199.                
  200.                 BTree == {ElementAtom, Height, {},{}} -> {};
  201.                
  202.                 %Hier wird der richtige Ersatz des rechten Teilbaumes gesucht, die Ursprüngliche Node mit dem Ersatz gelöscht und ein korrekter Ersatzbaum wir zurückgegeben.
  203.                 BTree == {ElementAtom, Height, Links,Rechts} ->
  204.                     Kleinster = kLZahl(Rechts), %Findet uns die Kleinste Zahl vom übergebenen Baum
  205.                     RechtsNeu = deleteBT(Rechts, Kleinster), %Der Node von dem wir den Ersatzwert nehmen, wird gelöscht
  206.                     Hanoi = findHeight(RechtsNeu, Links),
  207.                     {Kleinster, Hanoi, Links, RechtsNeu};
  208.                 true -> -1
  209.                 end;
  210.         true -> -1
  211.         end.
  212. kLZahl({ElementAtom, _Height, {}, _Rechts}) ->
  213.     ElementAtom;
  214. kLZahl({_ElementAtom, _Height, Links, _Rechts}) ->
  215.     kLZahl(Links).
  216.  
  217.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement