[Pascal] Drzewo BST k-rzadkie

arkadiusz992
Użytkownik
Użytkownik
Posty: 9
Rejestracja: 11 wrz 2012, o 14:58
Płeć: Mężczyzna
Lokalizacja: Warszawa
Podziękował: 5 razy

[Pascal] Drzewo BST k-rzadkie

Post autor: arkadiusz992 »

Mam problem z poniższym zadaniem, mianowicie wiem że da się zrobić to zadanie łatwiej jednak chciałbym jeszcze sam się zastanowić jak to rozwiązać nie używając list. A teraz chodzi mi o to czy to rozwiązanie choć przydługie jest poprawne. Z góry dziękuje za pomoc.


Zadanie 2 (egzamin poprawkowy z WDI 8.09.2011)
Drzewo BST o kluczach całkowitych jest k-rzadkie, jeśli moduł różnicy kluczy z każdych dwóch różnych wierzchołków jest większy od k.
Napisz procedurę, która dla danego drzewa BST o kluczach całkowitych i liczby k sprawdzi czy to drzewo jest k-rzadkie.

Opis algorytmu : tworze z drzewa liste posortowana rosnaco a nastepnie sprawdzam kazde sasiadujace ze soba elementy tej listy,
jesli modul roznicy kazdych dwoch sasiadujacych ze soba elementow jest wiekszy od k to jest ona k-rzadka.

Kod: Zaznacz cały

function zad2(r:wsk; k:integer):boolean;
  var
    l:lista;

  procedure dodaj na liste(i:integer);
    var
      t:lista;
    begin
      new(t);
      t^.liczba:=i;
      t^.next:=l;
      l:=t;
    end;

  procedure stworz_liste(v:wsk);
  begin
    if v<>nil then begin
      stworz_liste(v^.lewy);
      dodaj na liste(v^.liczba);
      stworz_liste(v^.prawy);
    end;
  end;

  function sprawdz_liste(c:lista):boolean;
    var
      z:boolean;
      d:integer;
    begin
      if c<>nil then
        if c^.next=nil then z:=false        {lista ma jeden element czyli drzewo nie jest k-rzadkie}
        else begin
          z:=true;
	  while (z=true) and (c^.next<>nil) do begin
    	    if (c^liczba-c^.next^.liczba<0) then d:=c^.next^.liczba-c^.liczba
	      else d:=c^liczba-c^.next^.liczba;
	    if d>k then c:=c^.next
  	      else z:=false;
	  end;
        end
      else z:=false;
    sprawdz_liste:=z;
    end;

begin
  l:nil;
  stworz_liste(r);
  zad2:=sprawdz_liste(l);
end;
     
Ostatnio zmieniony 11 wrz 2012, o 17:41 przez Afish, łącznie zmieniany 1 raz.
Powód: Staraj się lepiej dobierać nazwy tematów, tak by wskazywały o czym jest treść zadania.
royas
Użytkownik
Użytkownik
Posty: 363
Rejestracja: 24 sie 2012, o 09:27
Płeć: Mężczyzna
Lokalizacja: Cieszyn
Pomógł: 80 razy

Problem z drzewami BST, pascal(I rok studiów)

Post autor: royas »

Tak z grubsza wygląda dobrze. Lista powinna być posortowana niemalejąco, więc niepotrzebnie sprawdzasz czy c^.liczna czy c^.next^.liczba jest większe (tam brakuje kropki).

Co rozwiązania bez listy:
Ukryta treść:    
adambak
Użytkownik
Użytkownik
Posty: 1272
Rejestracja: 8 sty 2011, o 18:18
Płeć: Mężczyzna
Lokalizacja: Warszawa
Podziękował: 295 razy
Pomógł: 115 razy

Problem z drzewami BST, pascal(I rok studiów)

Post autor: adambak »

drzewo z jednym wierzchołkiem, tak jak i puste, jest k-rzadkie
arkadiusz992
Użytkownik
Użytkownik
Posty: 9
Rejestracja: 11 wrz 2012, o 14:58
Płeć: Mężczyzna
Lokalizacja: Warszawa
Podziękował: 5 razy

Problem z drzewami BST, pascal(I rok studiów)

Post autor: arkadiusz992 »

A czy byliby Panowie skłonni sprawdzić czy następujące zadanie rozwiązałem poprawnie?

zadanie
Napisać funkcję, która dla danego drzewa BST o kluczach całkowitych oblicza, ile jest różnych kluczy w tym drzewie.

u nas przyjmuje się że drzewo BST ma w lewym poddrzewie wierzchołki o kluczach nie większych a w prawym ściśle większe.

Kod: Zaznacz cały

function zad2(r:wsk):integer;
  var
    i:integer;
  procedure pom(r:wsk; k:integer);
    var
      kl, kp : integer;
    begin
      if r=nil then k:=0
	else begin
	  pom(r^.lewy, kl);
	  pom(r^.prawy, kp);
	  if (kl=0) and (kp=0) then k:=1
	    else
	      if (r^.lewy^.klucz=r^.klucz) then k:=kl+kp
   	        else k:=kl+kp+1;
        end;
    end;

begin
pom(r,i);
zad2:=i;
end;
royas
Użytkownik
Użytkownik
Posty: 363
Rejestracja: 24 sie 2012, o 09:27
Płeć: Mężczyzna
Lokalizacja: Cieszyn
Pomógł: 80 razy

Problem z drzewami BST, pascal(I rok studiów)

Post autor: royas »

Raczej coś nie tak. Czy dla drzewa powstałego przez wstawianie po kolei 3,2,1 będzie dobry wynik?
arkadiusz992
Użytkownik
Użytkownik
Posty: 9
Rejestracja: 11 wrz 2012, o 14:58
Płeć: Mężczyzna
Lokalizacja: Warszawa
Podziękował: 5 razy

Problem z drzewami BST, pascal(I rok studiów)

Post autor: arkadiusz992 »

royas, Rzeczywiście to co napisałem jest niepoprawne. Ale jeżeli zmieniłbym nagłówek procedury pom tak że przy k dopisze var ( procedure pom(r:wsk; var k:integer) to sądzi Pan że procedura będzie działała poprawnie?
royas
Użytkownik
Użytkownik
Posty: 363
Rejestracja: 24 sie 2012, o 09:27
Płeć: Mężczyzna
Lokalizacja: Cieszyn
Pomógł: 80 razy

[Pascal] Drzewo BST k-rzadkie

Post autor: royas »

Edit: A, przepraszam. Zasugerowałem się nazwą zmiennej.
Problem inny się pojawi. Jeśli w danym węźle jest prawe poddrzewo a lewego nie ma, to nie uda się porównanie klucza lewego syna z kluczem aktualnego węzła. (r^.lewy^.klucz=r^.klucz).
Pozatym wygląda dobrze. Choć ładniej by to było zrobić funkcją a nie przekazywaniem przez referencje (var k:integer).
arkadiusz992
Użytkownik
Użytkownik
Posty: 9
Rejestracja: 11 wrz 2012, o 14:58
Płeć: Mężczyzna
Lokalizacja: Warszawa
Podziękował: 5 razy

[Pascal] Drzewo BST k-rzadkie

Post autor: arkadiusz992 »

royas, Zgadzam się całkowicie że poprzednie rozwiązanie jest błędne. A co sądzi Pan o tym rozwiązaniu?

zadanie 2(egz z WDI 06.06.2011)
Napisać funkcję, która dla danego drzewa BST o kluczach całkowitych oblicza, ile jest różnych kluczy w tym drzewie.

Kod: Zaznacz cały

function oblicz(r:wsk):integer;
  var
    b:boolean;
    k:integer;
    
  procedure pom(r:wsk; var b:boolean; var k:integer);
    var
      bl, bp : boolean;
      kl, kp : integer;
    begin
      if r=nil then begin
        k:=0;
	b:=true;
      end
      else begin
	pom(r^.lewy, bl, kl);
	pom(r^.prawy, bp, kp);
	b:=bl and bp and ((r^.lewy=nil) or (r^.lewy^.klucz<>r^.klucz));
	if b=true then begin 
 	  k:=kl+kp+1;
	  u:=r;
	end
	else
	  if kl<kp then begin
	    u:=up;
	    k:=kp;
	  end
	  else begin
	    u:=ul;
	    k:=kl;
 	  end;
      end;
    end;

begin
pom(r, b, k);
oblicz:=k;
end;
royas
Użytkownik
Użytkownik
Posty: 363
Rejestracja: 24 sie 2012, o 09:27
Płeć: Mężczyzna
Lokalizacja: Cieszyn
Pomógł: 80 razy

[Pascal] Drzewo BST k-rzadkie

Post autor: royas »

Co to jest "u"?
Trick z "or" może nie zadziałać, bo "or" może być gorliwy zależnie od wersji i kompilatora. W rozszerzeniach jest or_else (leniwy), ale w całkiem zwykłym Pascalu go nie ma.

Wydaje mi się, że próbujesz skorzystać z błędnego założenia, że jeśli gdzieś się powtarzają klucze, to tworzą one "ciąg lewych synów". Czyli że jeśli w drzewie występuje 2 razy "2", to będzie ona
w pewnym węźle i w jego lewym synu. Nie musi tak być. Np. jeśli BST będzie tworzone przez kolejne wstawianie do niego 2,1,2, to w korzeniu będzie 2, w lewym synu 1, a w prawym synu lewgo syna znowu 2. Tak, że klucz korzenia będzie inny niż klucz lewego syna.

Trzeba by pójść w stronę, że pom oprócz liczby unikalnych kluczy zwraca klucz maksymalny w poddrzewie.
arkadiusz992
Użytkownik
Użytkownik
Posty: 9
Rejestracja: 11 wrz 2012, o 14:58
Płeć: Mężczyzna
Lokalizacja: Warszawa
Podziękował: 5 razy

[Pascal] Drzewo BST k-rzadkie

Post autor: arkadiusz992 »

Wkleiłem procedurę której nie chciałem w treść poprzedniego postu. A co do Pana przykładu dla 2,1,2 to u nas można zakładać że w prawym poddrzewie są wierzchołki o kluczach ściśle większych a w lewym o nie większych. Wiem że to nie jest poprawna definicja przynajmniej wg wikipedi lecz myślę że dalej będę się tego trzymał. Wklejam w końcu to co chciałem wkleić wcześniej i czekam na Pański komentarz

Kod: Zaznacz cały

zadanie 2(egz z WDI 06.06.2011)
Napisać funkcję, która dla danego drzewa BST o kluczach całkowitych oblicza, ile jest różnych kluczy w tym drzewie.

function pom(r:wsk):integer;
    begin
      if r=nil then  pom(r):=0;
      else 
	if r^.lewy<>nil then
	  if r^.lewy^.klucz<>r^.klucz then pom(r):=pom(r^.prawy)+pom(r^.lewy)+1
	    else pom(r):=pom(r^lewy)+pom(r^.prawy)
	else pom(r):=pom(r^.prawy)+1;
    end;
royas
Użytkownik
Użytkownik
Posty: 363
Rejestracja: 24 sie 2012, o 09:27
Płeć: Mężczyzna
Lokalizacja: Cieszyn
Pomógł: 80 razy

[Pascal] Drzewo BST k-rzadkie

Post autor: royas »

Ale podane drzewo 2,1,2 spełnia te założenia, niestety. Pierwsza 2 w korzeniu, pozostałe 1,2 w lewym poddrzewie, 1 korzeniem tego lewego poddrzewa, druga 2 na prawo od 1.
arkadiusz992
Użytkownik
Użytkownik
Posty: 9
Rejestracja: 11 wrz 2012, o 14:58
Płeć: Mężczyzna
Lokalizacja: Warszawa
Podziękował: 5 razy

[Pascal] Drzewo BST k-rzadkie

Post autor: arkadiusz992 »

Poddaję się z tym zadaniem na razie ale dziękuje za wszystkie uwagi do niego. Zabrałem się właśnie za zadanie z list jednokierunkowych więc może ma Pan ochotę spojrzeć czy chociaż jego rozwiązanie jest poprawne.

zadanie 2 (egzamin z WDI 31.08.09)
Dana jest lista liczb całkowitych. Napisać procedurę, która rozdzieli tę listę na 3 listy
z zachowaniem uporządkowania, w taki sposób, żeby jedna lista zawierała elementy podzielne
przez 2, druga podzielne przez 3 ale nie przez 2, a trzecia pozostałe elementy.

Kod: Zaznacz cały

procedure rozdziel(l:lista; var l1:lista; var l2:lista; var l3:lista);
  var
    v:lista;
  procedure dodaj(u:lista; var t:lista);
    var
      w:lista;
    begin
      u^.next:=nil;
      if t=nil then t:=l
        else begin
          w:=t;
          while (w^.next<>nil) do w:=w^.next;
          w^.next:=l;
        end;
    end;
	

  begin
    l1:=nil;
    l2:=nil;
    l3:=nil;
    if l<>nil then
      while l<>nil do begin
        if (l^.klucz mod 2)=0 then begin
          v:=l^.next;
          dodaj(l, l1);
          l:=v;
        end 
          else if (l^.klucz mod 3)=0 then begin
            v:=l^.next;
            dodaj(l, l2);
            l:=v;
          end
            else begin
              v:=l^.next;
              dodaj(l, l3);
              l:=v;
            end;
      end;
royas
Użytkownik
Użytkownik
Posty: 363
Rejestracja: 24 sie 2012, o 09:27
Płeć: Mężczyzna
Lokalizacja: Cieszyn
Pomógł: 80 razy

[Pascal] Drzewo BST k-rzadkie

Post autor: royas »

To wygląda dobrze. Można by jeszcze kosmetycznie v:=l^.next; i l:=v;
wyrzucić przed i za blok ifów. Inna sprawa, która by nieco komplikowała, ale niewiele: jeśli wiadomo, że do listy będziemy dodawać dużo elementów, to warto mieć też wskaźnik na ostatni element listy, żeby przy każdym dodaniu nie trzeba było tego while'a w "dodaj" wykonywać.

A jeśli chcesz posprawdzać czyjś kod to taki mam pomysł na te różne klucze ale pewny nie jestem:
Ukryta treść:    
arkadiusz992
Użytkownik
Użytkownik
Posty: 9
Rejestracja: 11 wrz 2012, o 14:58
Płeć: Mężczyzna
Lokalizacja: Warszawa
Podziękował: 5 razy

[Pascal] Drzewo BST k-rzadkie

Post autor: arkadiusz992 »

Rzeczywiście ma Pan racje. Jeśli ma Pan ochotę dalej mi pomagać to oto następne zadanie.

zadanie 3 (31.08.09)
Dane jest drzewo, którego węzłý zawierają liczby całkowite. Napisać funkcje, która zwraca wskaźnik do korzenia
maksymalnego pod względem wysokości poddrzewa zawierającego same liczby parzyste.]

Pytanie: Co powinno się stać gdy kluczem wierzchołka będzie liczba 0 ?

Kod: Zaznacz cały

function zad(r:wsk):wsk;
  var
    u:wsk;
    z:boolean;
    h:integer;
  procedure pom(r:wsk; var u:wsk; var z:boolean; var h:integer);
    var
      ul, up:wsk;  zl, zp:boolean;  hl, hp:integer;
    begin
      if r=nil then begin
        u:=nil;
        z:=True;
        h:=0;
      end
      else begin
        pom(r^.lewy, ul, zl, hl);
        pom(r^.prawy, up, zp, hp);
        if (r^.klucz mod 2= 1) then begin
          if hl<hp then begin 
            h:=hp;
            u:=up;
          end
          else begin
            h:=hl;
            u:=ul;
          end;
          z:=false;
        end
        else
          if (zp=true) and (zl=true) then begin
            z:=True;
            u:=r;
            if hl<hp then h:=hp+1
              else h:=hl+1;
          end
          else begin
            z:=false;
            if hl<hp then begin
              h:=hp;
              u:=up;
            end
            else begin
              h:=hl;
              u:=ul;
            end;
          end;
      end;

begin
pom(r, u, z, h);
zad(r):=u;
end;
royas
Użytkownik
Użytkownik
Posty: 363
Rejestracja: 24 sie 2012, o 09:27
Płeć: Mężczyzna
Lokalizacja: Cieszyn
Pomógł: 80 razy

[Pascal] Drzewo BST k-rzadkie

Post autor: royas »

Wygląda ok.
ODPOWIEDZ