Serwis Edukacyjny w I-LO w Tarnowie Materiały dla uczniów liceum |
Wyjście Spis treści Wstecz Dalej Autor artykułu: mgr Jerzy Wałaszek |
©2024 mgr Jerzy Wałaszek |
ProblemMając dwie listy posortowane, należy je scalić w jedną listę, która jest posortowana. |
Zadanie rozwiązujemy przy pomocy przeglądania liniowego, usuwania pierwszych elementów oraz wstawiania na koniec listy. Algorytm porównuje cyklicznie pierwsze elementy scalanych list i usuwa z nich element mniejszy, który następnie wstawia na koniec listy wynikowej. W ten sposób elementy będą posortowane rosnąco na liście wynikowej. Przeglądanie list scalanych trwa do momentu, aż w jednej z nich (lub w obu jednocześnie) skończą się elementy. W takim przypadku na koniec listy wynikowej zostają dopisane pozostałe elementy tej listy scalanej, która je posiada.
K01: l_push_front(h, 0) ; wstaw na listę h fałszywy element K02: p ← h ; p wskazuje fałszywy element listy h K03: Dopóki h1 ≠ nil h2 ≠ nil, ; dopóki scalane listy obie nie są puste, wykonuj kroki K04…K10 ; scalamy ich elementy w pętli K04: Jeśli h1→data > h2→data, ; wybieramy mniejszy element to idź do kroku K08 ; z początków list h1, h2 K05: p→next ← h1 ; wstawiamy go na koniec listy h K06: h1 ← h1→next ; wybrany element usuwamy z jego listy K07: Idź do kroku K10 K08: p→next ← h2 K09: h2 ← h2→next K10: p ← p→next ; przechodzimy do dodanego elementu, ; czyli do ostatniego elementu listy h K11: Jeśli h1 ≠ nil, ; do końca h dodajemy końcówkę listy h1, to p→next ← h1 h1 ← nil K12: Jeśli h2 ≠ nil, ; do końca h dodajemy końcówkę listy h2, to p→next ← h2 h2 ← nil K13: l_pop_front(h) ; usuwamy z początku h fałszywy element K14: Zakończ
Pascalprocedure l_merge(var h1, h2, h : PSLel); var p : PSLel; begin l_push_front(h, 0); // fałszywy element p := h; while(h1 <> nil) and (h2 <> nil) do begin if h1^.data > h2^.data then begin p^.next := h2; h2 := h2^.next; end else begin p^.next := h1; h1 := h1^.next; end; p := p^.next; end; if h1 <> nil then begin p^.next := h1; h1 := nil; end; if h2 <> nil then begin p^.next := h2; h2 := nil; end; l_pop_front(h); // fałszywy element end; |
void l_merge(SLel * & h1, SLel * & h2, SLel * & h) { SLel * p; l_push_front(h, 0); p = h; while(h1 && h2) { if(h1->data > h2->data) { p->next = h2; h2 = h2->next; } else { p->next = h1; h1 = h1->next; } p = p->next; } if(h1) { p->next = h1; h1 = NULL; } if(h2) { p->next = h2; h2 = NULL; } l_pop_front(h); } |
BasicSub l_merge(ByRef h1 As SLel Ptr, _ ByRef h2 As SLel Ptr, _ ByRef h As SLel Ptr) Dim p As SLel Ptr l_push_front(h, 0) p = h while(h1 <> 0) AndAlso (h2 <> 0) If h1->data > h2->data Then p->next = h2 h2 = h2->next Else p->next = h1 h1 = h1->next End If p = p->next Wend If h1 <> 0 Then p->next = h1 h1 = 0 End If If h2 <> 0 Then p->next = h2 h2 = 0 End If l_pop_front(h) End Sub |
Python (dodatek) |
# klasa elementu listy #--------------------- class SLel: def __init__(self, data): self.next = None self.data = data # klasa listy jednokierunkowej #----------------------------- class SLvar: # Konstruktor def __init__(self): self.head = None # Dodaje nowy element na początek def l_push_front(self, v): p = SLel(v) p.next = self.head self.head = p # Usuwa element z początku def l_pop_front(self): p = self.head if p: self.head = p.next p = None # łączy listy posortowane def l_merge(self, h1, h2): self.l_push_front(0) p = self.head while h1.head and h2.head: if h1.head.data > h2.head.data: p.next = h2.head h2.head = h2.head.next else: p.next = h1.head h1.head = h1.head.next p = p.next if h1.head: p.next = h1.head h1.head = None if h2.head: p.next = h2.head h2.head = None self.l_pop_front() |
Uwaga: Zanim uruchomisz program, przeczytaj wstęp do tego artykułu, w którym wyjaśniamy funkcje tych programów oraz sposób korzystania z nich. |
Program tworzy dwie listy uporządkowane i scala je w jedną listę uporządkowaną. Program wykorzystuje obiekt listy jednokierunkowej. |
Pascal// Scalanie dwóch posortowanych list jednokierunkowych // Data: 25.02.2012 // (C)2020 mgr Jerzy Wałaszek //---------------------------------------------------- program slist_merge; // Typ elementów listy //-------------------- type PSLel = ^SLel; SLel = record next : PSLel; data : char; end; // Definicja typu obiektowego slist //--------------------------------- SLvar = object public head : PSLel; // początek listy constructor init; destructor destroy; function l_len : cardinal; procedure l_print; procedure l_push_front(v : char); procedure l_pop_front; procedure l_merge (var h1, h2 : SLvar); end; //------------------------ // Metody obiektu SLvar //------------------------ // Konstruktor-inicjuje pole head //--------------------------------- constructor SLvar.init; begin head := nil; end; // Destruktor-usuwa listę z pamięci //----------------------------------- destructor SLvar.destroy; begin while head <> nil do l_pop_front; end; // Funkcja oblicza liczbę elementów listy //--------------------------------------- function SLvar.l_len : cardinal; var c : cardinal; p : PSLel; begin c := 0; p := head; while p <> nil do begin inc(c); p := p^.next; end; l_len := c; end; // Procedura wyświetla zawartość elementów listy //---------------------------------------------- procedure SLvar.l_print; var p : PSLel; begin write(l_len, ' : '); p := head; while p <> nil do begin write(p^.data); p := p^.next; end; writeln; end; // Procedura dołączania na początek listy //--------------------------------------- procedure SLvar.l_push_front(v : char); var p : PSLel; begin new(p); p^.next := head; p^.data := v; head := p; end; // Procedura usuwa pierwszy element //--------------------------------- procedure SLvar.l_pop_front; var p : PSLel; begin p := head; if p <> nil then begin head := p^.next; dispose(p); end; end; // Scala dwie obce listy //---------------------- procedure SLvar.l_merge(var h1, h2 : SLvar); var p : PSLel; begin l_push_front(#0); p := head; while(h1.head <> nil) and (h2.head <> nil) do begin if h1.head^.data > h2.head^.data then begin p^.next := h2.head; h2.head := h2.head^.next; end else begin p^.next := h1.head; h1.head := h1.head^.next; end; p := p^.next; end; if h1.head <> nil then begin p^.next := h1.head; h1.head := nil; end; if h2.head <> nil then begin p^.next := h2.head; h2.head := nil; end; l_pop_front(); end; //--------------- // Program główny //--------------- var L1, L2, L : SLvar; // listy jednokierunkowe c, i : integer; z : char; begin Randomize; L1.init; // inicjujemy obiekty L2.init; L.init; c := 1+random(2); z := char(78+random(13)); for i := 1 to 20 do begin L1.l_push_front(z); dec(c); if c = 0 then begin c := 1+random(2); if z > 'A' then dec(z); end; end; L1.l_print; c := 1+random (2); z := char(78+random(13)); for i := 1 to 30 do begin L2.l_push_front(z); dec(c); if c = 0 then begin c := 1+random(3); if z > 'A' then dec(z); end; end; L2.l_print; writeln; L.l_merge(L1, L2); L.l_print; L.destroy; end. |
// Scalanie dwóch posortowanych list jednokierunkowych // Data: 25.02.2012 // (C)2020 mgr Jerzy Wałaszek //---------------------------------------------------- #include <iostream> #include <cstdlib> #include <ctime> using namespace std; // Typ elementów listy //-------------------- struct SLel { SLel * next; char data; }; // Definicja typu obiektowego SLvar //------------------------------------ class SLvar { public: SLel * head; SLvar(); // konstruktor ~SLvar(); // destruktor unsigned l_len(); void l_print(); void l_push_front(char v); void l_pop_front(); void l_merge(SLvar & l1, SLvar & l2); }; // Konstruktor listy //------------------ SLvar::SLvar() { head = NULL; } // Destruktor listy //----------------- SLvar::~SLvar() { while(head) l_pop_front(); } // Funkcja oblicza liczbę elementów listy //--------------------------------------- unsigned SLvar::l_len() { unsigned c = 0; SLel * p = head; while(p) { c++; p = p->next; } return c; } // Procedura wyświetla zawartość elementów listy //---------------------------------------------- void SLvar::l_print() { SLel * p; cout << l_len() << ": "; for(p = head; p; p = p->next) cout << p->data; cout << endl; } // Procedura dołączania na początek listy //--------------------------------------- void SLvar::l_push_front(char v) { SLel * p; p = new SLel; p->next = head; p->data = v; head = p; } // Procedura usuwa pierwszy element //--------------------------------- void SLvar::l_pop_front() { SLel * p = head; if(p) { head = p->next; delete p; } } // Scala dwie obce listy //---------------------- void SLvar::l_merge(SLvar & h1, SLvar & h2) { SLel * p; l_push_front(0); p = head; while(h1.head && h2.head) { if(h1.head->data > h2.head->data) { p->next = h2.head; h2.head = h2.head->next; } else { p->next = h1.head; h1.head = h1.head->next; } p = p->next; } if(h1.head) { p->next = h1.head; h1.head = NULL; } if(h2.head) { p->next = h2.head; h2.head = NULL; } l_pop_front(); } //--------------- // Program główny //--------------- int main() { SLvar L1, L2, L; // listy jednokierunkowe int c, i; char z; srand(time(NULL)); c = 1+rand()%2; z = 78+rand()%13; for(i = 0; i < 20; i++) { L1.l_push_front(z); if(!--c) { c = 1+rand()%2; if(z > 'A') z--; } } L1.l_print(); c = 1+rand()%2; z = 78+rand()%13; for(i = 0; i < 30; i++) { L2.l_push_front(z); if(!--c) { c = 1+rand()%2; if(z > 'A') z--; } } L2.l_print(); cout << endl; L.l_merge(L1, L2); L.l_print(); return 0; } |
Basic' Scalanie dwóch posortowanych list jednokierunkowych ' Data: 25.02.2012 ' (C)2020 mgr Jerzy Wałaszek '---------------------------------------------------- ' Typ elementów listy '-------------------- Type SLel next As SLel Ptr data As String * 1 End Type ' Typ obiektowy slist '------------------------------ Type slistvAR head As SLel Ptr Declare Constructor() Declare Destructor() Declare Sub l_print() Declare Function l_len() As UInteger Declare Sub l_push_front(v As String) Declare Sub l_pop_front() Declare Sub l_merge(ByRef h1 As SLvar, _ ByRef h2 As SLvar) End Type '--------------- ' Program główny '--------------- Dim As SLvar L1, L2, L ' listy jednokierunkowe Dim As Integer c, i, z Randomize c = 1+Int(Rnd()*2) z = 78+Int(Rnd()*13) For i = 1 To 20 L1.l_push_front(Chr(z)) c -= 1 If c = 0 Then c = 1+Int(Rnd()*2) If z > 65 then z -= 1 End If Next L1.l_print() c = 1+Int(Rnd()*2) z = 78+Int(Rnd()*13) For i = 1 To 30 L2.l_push_front(Chr(z)) c -= 1 If c = 0 Then c = 1+Int(Rnd()*2) If z > 65 then z -= 1 End If Next L2.l_print() Print L.l_merge(L1, L2) L.l_print() End ' Konstruktor listy '------------------- Constructor SLvar() head = 0 End Constructor ' Destruktor listy '----------------- Destructor SLvar() While head l_pop_front() Wend End Destructor ' Procedura wyświetla zawartość elementów listy '---------------------------------------------- Sub SLvar.l_print() Dim p As SLel Ptr = head Print l_len();": "; While p Print p->Data; p = p->next Wend Print End Sub ' Funkcja oblicza liczbę elementów listy '--------------------------------------- Function SLvar.l_len() As UInteger Dim c As UInteger Dim p As SLel Ptr = head c = 0 While p c += 1 p = p->next Wend l_len = c End Function ' Procedura dołączania na początek listy '--------------------------------------- Sub SLvar.l_push_front(v As String) Dim p As SLel Ptr p = new SLel p->next = head p->data = v head = p End Sub ' Procedura usuwa pierwszy element '--------------------------------- Sub SLvar.l_pop_front() Dim p As SLel Ptr p = head ' zapamiętujemy początek If p Then head = p->next ' nowy początek Delete p ' usuń element z pamięci End If End Sub ' Scala dwie obce listy '---------------------- Sub SLvar.l_merge(ByRef h1 As SLvar, _ ByRef h2 As SLvar) Dim p As SLel Ptr l_push_front(Chr(0)) p = head while(h1.head <> 0) AndAlso (h2.head <> 0) If h1.head->data > h2.head->data Then p->next = h2.head h2.head = h2.head->next Else p->next = h1.head h1.head = h1.head->next End If p = p->next Wend If h1.head <> 0 Then p->next = h1.head h1.head = 0 End If If h2.head <> 0 Then p->next = h2.head h2.head = 0 End If l_pop_front() End Sub |
Python (dodatek) |
# Scalanie dwóch posortowanych # list jednokierunkowych # Data: 25.05.2024 # (C)2024 mgr Jerzy Wałaszek # ----------------------------- import random # klasa elementu listy # --------------------- class SLel: def __init__(self, data): self.next = None self.data = data # klasa listy jednokierunkowej # ----------------------------- class SLvar: # Konstruktor def __init__(self): self.head = None # Destruktor def __del__(self): while self.head: self.l_pop_front() # oblicza liczbę elementów listy def l_len(self): c = 0 p = self.head while p: c += 1 p = p.next return c # Wyświetla zawartość listy def l_print(self): print(self.l_len(), ": ", sep="", end="") p = self.head while p: print(p.data, end="") p = p.next print() # Dodaje nowy element na początek def l_push_front(self, v): p = SLel(v) p.next = self.head self.head = p # Usuwa element z początku def l_pop_front(self): p = self.head if p: self.head = p.next # Scala dwie obce listy def l_merge(self, h1, h2): self.l_push_front(0) p = self.head while h1.head and h2.head: if h1.head.data > h2.head.data: p.next = h2.head h2.head = h2.head.next else: p.next = h1.head h1.head = h1.head.next p = p.next if h1.head: p.next = h1.head h1.head = None if h2.head: p.next = h2.head h2.head = None self.l_pop_front() # --------------- # Program główny # --------------- # listy jednokierunkowe sl1 = SLvar() sl2 = SLvar() sl = SLvar() c = random.randrange(1, 3) z = random.randrange(78, 91) for i in range(20): sl1.l_push_front(chr(z)) c -= 1 if not c: c = random.randrange(1, 3) if z > ord('A'): z -= 1 sl1.l_print() c = random.randrange(1, 3) z = random.randrange(78, 91) for i in range(30): sl2.l_push_front(chr(z)) c -= 1 if not c: c = random.randrange(1, 3) if z > ord('A'): z -= 1 sl2.l_print() print() sl.l_merge(sl1, sl2) sl.l_print() |
Wynik: |
20: DDEFFGGHIIJJKLLMMNOO 30: CDDEFGHHIJJKLMNNOOPPQRRSSTTUVV 50: CDDDDEEFFFGGGHHHIIIJJJJKKLLLMMMNNNOOOOPPQRRSSTTUVV |
Zespół Przedmiotowy Chemii-Fizyki-Informatyki w I Liceum Ogólnokształcącym im. Kazimierza Brodzińskiego w Tarnowie ul. Piłsudskiego 4 ©2024 mgr Jerzy Wałaszek |
Materiały tylko do użytku dydaktycznego. Ich kopiowanie i powielanie jest dozwolone
pod warunkiem podania źródła oraz niepobierania za to pieniędzy.
Pytania proszę przesyłać na adres email:
Serwis wykorzystuje pliki cookies. Jeśli nie chcesz ich otrzymywać, zablokuj je w swojej przeglądarce.
Informacje dodatkowe.