120 likes | 210 Views
Vnitřní řazení s využitím dynamických struktur. Tvorba spojového seznamu je vcelku triviální záležitostí: Vytvořím prázdný seznam příkazem LIST:=nil → LIST (1) za předpokladu dříve deklarované proměnné var LIST: WSKAZ;
E N D
Vnitřní řazení s využitím dynamických struktur Tvorba spojového seznamu je vcelku triviální záležitostí: • Vytvořím prázdný seznam příkazem LIST:=nil → LIST (1) za předpokladu dříve deklarované proměnné var LIST: WSKAZ; opírající se o potřebné definice typů např. ve tvaru type COSI = string[10] {popř. COSI = integer apod.} WSKAZ = ^STRU; STRU = record IM: COSI; WS: WSKAZ end; nil
Zařazujeme do spojového seznamu prvky v pořadí jejich příchodů. Za předpokladu deklarace var Novy: WSKAZ; pak tento postup řeší příkazy NEW(NOVY); (2) NOVY^.WS := LIST; (3) LIST := NOVY (4) NOVY (2) LIST (4) (3) Samozřejmou součástí musí být tak přiřazení vstupující hodnoty typu COSI do přidávací struktury např. NOVY^.IM:=‘Aneta‘popř. readln(NOVY^.IM)apod. (2´)
Po dalším zopakování příkazů (2), (2´), (3) a (4) dostávám tvar NOVY (2) LIST (2‘) (4) (3) Takto stále přidávám další a další struktury, přičemž první je stále poslední a každá nově vytvořená se umístí vždy na začátek spojového seznamu.
Procedura pro vložení nové struktury do spojového seznamu (na jeho počátek) pak může být ve tvaru: procedure INSNOVY(var L: WSKAZ; A: COSI); var POM: WSKAZ; begin NEW(POM); POM^.IM := A; POM^.WS := L; L := POM end;
Vytiskneme-li hodnoty umístěné do spojového seznamu procedurou TISK ve tvaru procedure TISK(L: WSK); begin while L <> nil do begin writeln(L^.IM); L := L^.WS end end; získávám seznam hodnot v opačném pořadí, než jsme je zadávali.
Zařazení nové vstupující hodnoty do spojového seznamu podle její velikosti – tj. její vřazení na příslušné místo spojového seznamu – vyžaduje poněkud odlišnější postup NOVY NEXT LIST PRE
Nechť ukazatel NEXT postupně ukazuje na jednotlivé prvky spojového seznamu (od NEXT:= LIST do NEXT:= nil). Je zřejmé, že je-li NOVY^.IM <= NEXT^.IM, patří nově zařazovaná hodnota před hodnotu, na kterou právě ukazuje NEXT. Budeme-li v ukazateli před udržovat adresu předchozího prvku tak jak je patrno z obrázku, je zařazení nového prvku již jednoduchou záležitostí: NOVY^.WS := NEXT; PRE^.WS := NOVY; NEXT := nil {prvek je zařazen}
Ještě vyřeším obligátní záležitosti okrajových řešení: • patří-li nový prvek na začátek spojového seznamu, tj. NEXT = LIST, pak jeho zařazení řeší příkazy NOVY^.WS := LIST; LIST := NOVY; NEXT := nil {prvek je zařazen} • patří-li nový prvek na konec spojového seznamu, tj. NEXT = nil, pak jeho zařazení řeší příkazy NOVY^.WS := NEXT; {totéž jako NOVY^.WS := nil} PRE^.WS := NOVY; Kompletní řešení problematiky tvorby uspořádaného spojového seznamu přináší Příklad tvorby uspořádaného seznamu
Je zřejmé, že aplikace metod uváděných v souvislosti s vnitřním řazením v poli je vcelku zbytečná. Přesto, existuje-li již neuspořádaný spojový seznam, je možno tu či onu metodu s větší či menší efektivitou použít. Jako výhodná se jistě jeví další vkládací metoda přímého výběru (straight selection) a pro zajímavost uvedeme i metodu quicksort.
Procedure STRSEL(var FLIST:WSKAZ); var FIRST, NEXT, PRE, HLED, POM : WSKAZ; begin FIRST:=FLIST; FLIST:=nil; repeat HLED:=FIRST; NEXT:=FIRST^.WS; POM:=FIRST; repeat if NEXT^.IM>HLED^.IM then begin PRE:=POM; HLED:=NEXT end; POM:=NEXT; NEXT:=NEXT^.WS until NEXT=nil; if HLED=FIRST then begin POM:=FIRST^.WS; FIRST^.WS:=LIST; LIST:=FIRST; FIRST:=POM end else begin PRE^.WS:=HLED^.WS; HLED^.WS:=LIST; LIST:=HLED; end until FIRST^.WS=nil; FIRST^.WS:=LIST; LIST:=FIRST end;
Procedure QUICKSORT(var ZAC, KON: WSKAZ); procedure ROZDEL(var ZAC, KON : WSKAZ); var pivot, POM, NEXT : WSKAZ; begin pivot := ZAC; POM := pivot^.WS; NEXT := pivot; repeat if POM^.IM < pivot^.IM then begin {hodnota je mensi, strcime pred pivota} {premostime diru vzniklou odstranenim prvku} NEXT^.WS := POM^.WS; {presuneme prvek na spravne misto} POM^.WS := ZAC; ZAC := POM; if POM=KON then KON:=NEXT end else begin {posuneme se na dalsi prvek} NEXT := POM; end; POM := NEXT^.WS; until (POM=nil) or (POM=KON^.WS); if ZAC <> pivot then ROZDEL(ZAC, pivot); if (pivot <> KON) and (pivot^.WS <> KON) and (pivot^.WS <> nil) then ROZDEL(pivot^.WS, KON); end; begin rozdel(ZAC, KON); end;
Ukázka konkrétního programu s oběma výše uvedenými podprogramy je „Příklad řazení v dynamických strukturách“