Algorytm szukania liniowego

Wątek przeniesiony 2014-05-19 12:41 z Delphi i Pascal przez ŁF.

0
Program liniowe;
 uses CRT;
 Type tablica=array [1..20] of integer;
 var t:tablica;
     y:word;

  Procedure ZapiszTablice (var t:tablica);
   var i:byte;
    begin
     Randomize;
     for i:=1 to 20 do
     t[i]:= random (20);
    end;

  Function FindFirst(n:byte; t:tablica; y:integer) : integer;
   var i:byte;
    begin
     while (i<=n) and (y<>t[i]) do
      i:= i+1;
     if y= t[i] then FindFirst:= i
     else FindFirst:= -1;
    end;


  Procedure PiszTab (t:tablica);
   var i:byte;
    begin
     for i:=1 to 20 do
     write (t[i]:4);
     writeln;
    end;

 begin
  clrscr;
   writeln ('wyszukiwanie elementu w zbiorze nieuporzadkowanym');
   writeln ('podaj liczbe, ktorej szukasz: ');
   readln (y);
    if FindFirst (20, t, y)= -1
    then writeln ('brak szukanego elementu w zbiorze');  
     else writeln ('szukany element wystapil po raz pierwszy na pozycji ', FindFirst (20,t,y));
    repeat until keypressed;
 end.

Witam. Piszę z zaptaniem jak do jasnej ciasnej wyświetlić pozycję szukanego elementu?! Moja opcja w ogóle nie chce zadziałać chyba że mam coś nie tak z kompilatorem.

dodanie znacznika <code class="pascal"> - furious programming

0

Przeanalizuj sobie działanie funkcji FindFirst lub użyj debugera.

0

Czyli mam rozumieć że funkcja FindFirst ma szukać y<t[i]? W końcu sama nazwa na to wskazuje. A może jeszcze prościej:

function FindFirst (n:byte; t:tablica; y:integer) : integer;
var
    i:integer;
i:=1;
While (i<n) And (t[i]<y) Do i:=i+1;
If t[i]=y Then WriteLn('JEST')
Else WriteLn('BRAK');

??

dodanie znacznika <code class="pascal"> - furious programming

0

Przeanalizuj warunek pętli While...do.
Dajesz tam jeśli

(i<n) and (t[i]<>y)

i jeśli to się zgadza (oba warunki) to zwiększ o 1.

dodanie znacznika <code class="pascal"> - furious programming

0

Już się pogubiłem.

  begin
     while (i<=n) and (y<>t[i]) do \\stawiam warunek
      i:= i+1;                             \\zwiększam o jeden
     if y= t[i] then FindFirst:= i     \\spełniony warunek
     else FindFirst:= -1;               \\niespełniony warunek
    end;

Co jest w tym nie tak? Gdzie nie spojrzę w googlach to ta funkcja tak wygląda (różnią się tylko znakami przy zmiennych).

dodanie znacznika <code class="pascal"> - furious programming

0

Stawiasz warunek (oba muszą być spełnione) i jeśli jest spełniony to zwiększasz o 1 czyli np dla tablicy (1,2,3,4,(...)1) szukasz liczby 5 i co?
Twój warunek dla i=0 to

(0<20) and (t[0]=1<>5)

nie jest spełniony, program wychodzi z pętli wykonuje się dalej (nie będzie wykonywał i:=i+1)

    if 5 = 1 then FindFirst:= 0     \\niespełniony warunek
     else FindFirst:= -1;               \\spełniony warunek
    end;

i koniec funkcji.</del>

// Ale namieszałem... Jeszcze chyba się nie obudziłem po weekendzie. Ustaw i:=1 przed While.

dodanie znacznika <code class="pascal"> - furious programming

0

Ogólnie chcę po prostu zastosować algorytm szukania liniowego, najlepiej tak żeby pasowało pod projekt 'Algorytm zapobiegania kolizji: szukanie liniowe i mieszanie podwójne'.

Sam algorytm mam, tablicę mam, zmienne mam, itp. Nie działa mi tylko wyświetlanie zmiennych na ekran, dokładniej w tym miejscu występuje błąd:

else writeln ('szukany element wystapil po raz pierwszy na pozycji ', FindFirst (20,t,y));

Edit. Problem po części naprawiony, należało w funkcji FindFirst uprzednio dopisać że i:=1;

EDIT.2. Ale ze mnie lama, wszystko fixed. Wystarczyło tylko usunąć średnik przed else. Ślepota -,-

dodanie znacznika <code class="pascal"> - furious programming

2
  Function FindFirst(n:byte; t:tablica; y:integer) : integer;
   var i:byte;
    begin
     i:=1;  // ustaw i na początek tablicy w twoim przypadku numerujesz tablicę od 1;
     while (i<=n) and (y<>t[i]) do
      i:= i+1;
     if y= t[i] then FindFirst:= i
     else FindFirst:= -1;
    end;

i usuń średnik po

then writeln ('brak szukanego elementu w zbiorze')

dodanie znacznika <code class="pascal"> - furious programming

0

Hah, widzę że olśniło nas w tym samym momencie.

1
function FindFirst(n:byte; t:tablica; y:integer):integer;
var i:integer;
begin
  for i:=1 to n do if y=t[i] then begin FindFirst:=i; exit; end;
  FindFirst:=-1;
end;
0

@Huffy - tak sobie patrzę na Twoją funkcję FindFirst i skoro nazwa sugeruje, że wyszukiwane będzie pierwsze wystąpienie, to powinieneś mieć także funkcję FindNext, która wyszuka kolejne wystąpienia; A skoro już mowa o takich funkcjach, to mogą one działać na podobnej zasadzie, jak RTLowskie funkcje FindFirst i FindNext, służace do wyszukiwania plików lub katalogów według zadanej ścieżki;

Skoro już się tak pozastanawiałem, to machnąłem na szybko przykładowy program, który realizuje takie funkcje:

type
  TNumbersArr = array [0 .. 19] of Integer;

type
  TNumberSearchRec = record
    Number: Integer;
    LastPos: Integer;
  end;

  procedure FillNumbersArray(var ANumbers: TNumbersArr; const ARange: Integer);
  var
    I: Integer;
  begin
    for I := Low(ANumbers) to High(ANumbers) do
      ANumbers[I] := Random(ARange);
  end;

  procedure ShowNumbersArray(var ANumbers: TNumbersArr);
  var
    I: Integer;
  begin
    Write(#10'Numebrs: ');

    for I := Low(ANumbers) to High(ANumbers) - 1 do
      Write(ANumbers[I], ', ');

    WriteLn(ANumbers[High(ANumbers)], #10);
  end;

  function FindFirstNumber(ANumber: Integer; var ANumbers: TNumbersArr; var ARec: TNumberSearchRec): Integer;
  var
    I: Integer;
  begin
    ARec.Number := ANumber;

    for I := Low(ANumbers) to High(ANumbers) do
      if ANumbers[I] = ANumber then
      begin
        Result := I;
        ARec.LastPos := I;
        Exit;
      end;

    Result := -1;
  end;

  function FindNextNumber(var ANumbers: TNumbersArr; var ARec: TNumberSearchRec): Integer;
  var
    I: Integer;
  begin
    for I := ARec.LastPos + 1 to High(ANumbers) do
      if ANumbers[I] = ARec.Number then
      begin
        Result := I;
        ARec.LastPos := I;
        Exit;
      end;

    Result := -1;
  end;

var
  naRandom:  TNumbersArr;
  nsrRandom: TNumberSearchRec;
  intToFind, intRange: Integer;
begin
  Randomize();

  Write('Type the number to find: ');
  ReadLn(intToFind);
  Write('Type the numbers range:  ');
  ReadLn(intRange);

  FillNumbersArray(naRandom, intRange);
  ShowNumbersArray(naRandom);

  if FindFirstNumber(intToFind, naRandom, nsrRandom) = -1 then
    Write('The number "', nsrRandom.Number, '" not found.')
  else
  begin
    Write('The number "', nsrRandom.Number, '" found at positions: ', nsrRandom.LastPos);

    while FindNextNumber(naRandom, nsrRandom) <> -1 do
      Write(', ', nsrRandom.LastPos);
  end;

  ReadLn;
end.

Przykładowe wyjscie programu:

Type the number to find: 3
Type the numbers range:  5

Numebrs: 2, 1, 1, 3, 4, 3, 3, 0, 4, 3, 2, 2, 4, 4, 0, 2, 2, 4, 1, 4

The number "3" found at positions: 3, 5, 6, 9

Może Ci się przyda, a jak nie, to może ktoś inny skorzysta.

0

Proponuję na dobry początek wypełnić czymś tablicę...

begin
  clrscr;
  ZapiszTablice(t); ///<--- o tu
   writeln ('wyszukiwanie elementu w zbiorze nieuporzadkowanym');
   writeln ('podaj liczbe, ktorej szukasz: ');
   readln (y);
    if FindFirst (20, t, y)= -1
    then writeln ('brak szukanego elementu w zbiorze');  
     else writeln ('szukany element wystapil po raz pierwszy na pozycji ', FindFirst (20,t,y));
    repeat until keypressed;
 end.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.