Algoritmizace v Delphi - 1. díl
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Algoritmizace v Delphi - 1. dílAlgoritmizace v Delphi - 1. díl

 

Algoritmizace v Delphi - 1. díl

Google       Google       30. 11. 2005       14 521×

V první lekci si ukážeme způsoby vyhledávání v polích, uděláme si rozbor binárního a sekvenčního vyhledávání a napíšeme aplikaci pro testování rychlostí obou algoritmů...

Minule jsme si na úvod popsali, co je to algoritmus. Můžeme ho také nazvat "obecnou metodou k dosažení nějakého výpočtu (výsledku)". Hned si uvedeme jednoduchý příklad:

Máme pole textových řetězců (např. jména) a chceme vyhledat konkrétně jeden z nich (třeba Jan Novák). Postup není složitý a pravděpodobně by napadl většinu z vás i bez znalosti programování. Stačí procházet jeden řetězec po druhém a porovnávat ho s hledaným řetězcem Jan Novák, dokud nedorazíme k tomu správnému. Ačkoliv se to třeba zdá až příliš jednoduché, jedná se o algoritmus známý jako tzv. sekvenční vyhledávání.

Existuje však i jiný způsob, jak najít Jana Nováka v našem pomyslném poli řetězců. Jestliže například víme, že se jedná o pole řazené podle příjmení, můžeme použít tzv. binární vyhledávání: nejdříve porovnáme přesně prostřední jméno v poli s Janem Novákem. Pokud je to Jan Novák, máme hotovo. Pokud ne (což je pravděpodobnější), začneme porovnávat příjmení podle abecedy. Takže, pokud je prostřední prvek pole abecedně před Novákem, dá se z toho usoudit, že Novák je ve druhé polovině pole (samozřejmě, pokud je prostřední prvek za Novákem, patří Novák do poloviny první). Nyní můžeme udělat v podstatě to samé. Podíváme se na prostřední prvek vybrané části pole (první či druhá polovina) a opět porovnáváme s Novákem. Poté opět rozdělíme na půl, porovnáme prostřední prvek, ... a takto bychom pokračovali, dokud bychom Nováka nenašli.

Tento postup je určitě o něco kopmlikovanější než původní sekvenční vyhledávání, které může být zapsáno jednoduchým kódem pomocí for cyklu. Kód pro binární vyhledávání vyžaduje o něco více výpočtů a lokálních proměnných.

Pro lepší představu uvedu zdrojové kódy obou metod vyhledávání:


// sekvenční vyhledávání
function SeqSearch(Strings: Array of String; PocetPrvku: Integer; Hodnota: String): Integer;
{ Strings - pole stringů (textových řetězců) ve kterém se bude vyhledávat,
  PocetCisel - počet prvků v poli,
  Hodnota - hledaná hodnota }
var i: Integer;
begin
for i := 0 to pred(Count) do	// opakovat tolikrát, kolik je prvků v poli
  if CompareText(Strings[i], Value) = 0 then	// pokud se řetězec rovná hledanému...
    begin
    SeqSearch := i;	// ...hotovo
    Exit;
    end;
SeqSearch := -1;	// pokud nebyl prvek nalezen, vrátí funkce hodnotu -1
end;

// binární vyhledávání
function BinSearch(Strings: Array of String; PocetPrvku: Integer; Hodnota: String): Integer;
{ Strings - pole stringů (textových řetězců) ve kterém se bude vyhledávat,
  PocetCisel - počet prvků v poli,
  Hodnota - hledaná hodnota }
var L, R, M: Integer;
    Porovnani: Integer;
begin
L := 0;
R := Pred(Count);
while (L <= R) do	// opakovat, dokud se půlením nedostaneme až k jedinému číslu
  begin
  M := (L + R) div 2;
  CompareResult := CompareText(Strings[M], Value);
  if (CompareResult = 0) then
    begin
    BinSearch := M;
    Exit;
    end
      else if (CompareResult < 0) then
      L := M + 1
        else
        R := M - 1;
  end;
BinSearch := -1;
end;

Vzhledem k již zmíněné větší komplikovanosti binárního vyhledávání by se mohlo zdát, že sekvenční vyhledávání je rychlejší. Je ale těžké udělat si úsudek o rychlosti pouhým pročtením zdrojového kódu. Proto si napíšeme aplikaci, která bude testovat rychlosti obou způsobů.

Je jasné, že pokud pustíme pouze jeden vyhledávací cyklus, bude výsledná doba nejen téměř neměřitelná, ale výsledek bude i silně neobjektivní. Proto je nutné spustit vyhledávání vícekrát za sebou a pokaždé s jinými hodnotami. Pro účely tohoto testovacího programu použijeme čísla místo jmen. Postup u jmen by byl stejný, ale dalo by zbytečnou práci ukládání velkého množství jmen do pole. Při použití čísel není problém uložit data do pole za pomocí jednoduchého for cyklu.

Takže, postup bude následující: nejdříve zaplníme pole čísel, poté pomocí funkce Random určíme hledané číslo a nakonec číslo vyhledáme (nejdříve sekvenčním, potom binárním vyhledáváním). Toto (bez nahrávání hodnot do pole) budeme opakovat alespoň 10 000 krát. Jak dlouho celá operace trvala zjistíme pomocí funkce GetTickCount, která udává, kolik milisekund uběhlo od spuštění systému. Stačí si udělat dvě proměnné. Do první se uloží GetTickCount před vyhledáváním a do druhé až po skončení. První hodnotu odečteme od druhé a máme výsledný čas.

Pro úplnost ještě uvedu zdrojový kód obou vyhledávacích metod, upravených pro vyhledávání čísel:


// sekvenční vyhledávání
function SekVyhledavani(Cisla: Array of Integer; PocetCisel, Hodnota: Integer; var PocetKroku: Integer): Integer;
{ Cisla - pole čísel ve kterém se bude vyhledávat,
  PocetCisel - počet prvků v poli,
  Hodnota - hledaná hodnota,
  PocetKroku - počet podmínek if, který se musel vyhodnotit, aby byla hledaná hodnota nalezena }
var i: Integer;
begin
PocetKroku := 0;
for i := 0 to pred(PocetCisel) do     // opakovat tolikrát, kolik je prvků v poli
  begin
  if Cisla[i] = Hodnota then      // pokud se číslo rovná hledanému...
    begin
    SekVyhledavani := i;      // ...hotovo
    Exit;
    end;

  Inc(PocetKroku);      // podmínka if - zvýšit počet kroků
  end;
SekVyhledavani := -1;     // pokud nebyl prvek nalezen, vrátí funkce hodnotu -1
end;

// binární vyhledávání
function BinVyhledavani(Cisla: Array of Integer; PocetCisel, Hodnota: Integer; var PocetKroku: Integer): Integer;
{ Cisla - pole čísel ve kterém se bude vyhledávat,
  PocetCisel - počet prvků v poli,
  Hodnota - hledaná hodnota,
  PocetKroku - vrátí počet podmínek if, který se musel vyhodnotit, aby byla hledaná hodnota nalezena }
var L, R, M: Integer;
    Porovnani: Integer;
begin
PocetKroku := 0;
L := 0;
R := Pred(PocetCisel);
while (L <= R) do     // opakovat, dokud se půlením nedostaneme až k jedinému číslu
  begin
  M := (L + R) div 2;     // půlení intervalu
  Porovnani := Cisla[M] - Hodnota;    // porovnání prostředního prvku s hledaným
  if (Porovnani = 0) then     // pokud se rovná...
    begin
    BinVyhledavani := M;      // ...hotovo
    Inc(PocetKroku);      // porovnávání pomocí if - zvýšit počet kroků
    Exit;
    end
      else
      begin
      if (Porovnani < 0) then     // pokud je prostřední prvek menší než hledaný...
      L := M + 1      // ...hledaný prvek je ve druhé polovině
        else
        R := M - 1;     // ... hledaný prvek je v první polovině
      Inc(PocetKroku);      // podmínka if - zvýšit počet kroků
      end;
  end;
BinVyhledavani := -1;     // pokud nebyl prvek nalezen, vrátí funkce hodnotu -1
end;

Jistě jste si všimli, že kromě úpravy pro vyhledávání čísel, obsahují obě funkce i další změnu. Je jí proměnná PocetKroku. V té funkce vrací počet podmínek if, které bylo nutno vyhodnotit k vyhledání čísla. O tom však více až příště.

Pro dnešek je to všechno, více se mi toho sem již nevejde. Příště vám ukážu zdrojový kód testu rychlosti a ještě si ho trochu rozebereme. Zejména se zaměříme na výsledné hodnoty z testu a podíváme se, jak je to s efektivností obou vyhledávacích algoritmů.

×Odeslání článku na tvůj Kindle

Zadej svůj Kindle e-mail a my ti pošleme článek na tvůj Kindle.
Musíš mít povolený příjem obsahu do svého Kindle z naší e-mailové adresy kindle@programujte.com.

E-mailová adresa (např. novak@kindle.com):

TIP: Pokud chceš dostávat naše články každé ráno do svého Kindle, koukni do sekce Články do Kindle.

Hlasování bylo ukončeno    
0 hlasů
Google
Autor programuje v C++ a Delphi, zajímá se o muziku a sport.

Nové články

Obrázek ke článku Stavebnice umělé inteligence 1

Stavebnice umělé inteligence 1

Článek popisuje první část stavebnice umělé inteligence. Obsahuje lineární a plošnou optimalizaci.  Demo verzi je možné použít pro výuku i zájmovou činnost. Profesionální verze je určena pro vývojáře, kteří chtějí integrovat popsané moduly do svých systémů.

Obrázek ke článku Hybridní inteligentní systémy 2

Hybridní inteligentní systémy 2

V technické praxi využíváme často kombinaci různých disciplín umělé inteligence a klasických výpočtů. Takovým systémům říkáme hybridní systémy. V tomto článku se zmíním o určitém typu hybridního systému, který je užitečný ve velmi složitých výrobních procesech.

Obrázek ke článku Jak vést kvalitně tým v IT oboru: Naprogramujte si ty správné manažerské kvality

Jak vést kvalitně tým v IT oboru: Naprogramujte si ty správné manažerské kvality

Vedení týmu v oboru informačních technologií se nijak zvlášť neliší od jiných oborů. Přesto však IT manažeři čelí výzvě v podobě velmi rychlého rozvoje a tím i rostoucími nároky na své lidi. Udržet pozornost, motivaci a efektivitu týmu vyžaduje opravdu pevné manažerské základy a zároveň otevřenost a flexibilitu pro stále nové výzvy.

Obrázek ke článku Síla týmů se na home office může vytrácet. Odborníci radí, jak z pracovních omezení vytěžit maximum

Síla týmů se na home office může vytrácet. Odborníci radí, jak z pracovních omezení vytěžit maximum

Za poslední rok se podoba práce zaměstnanců změnila k nepoznání. Především plošné zavedení home office, které mělo být zpočátku jen dočasným opatřením, je pro mnohé už více než rok každodenní realitou. Co ale dělat, když se při práci z domova ztrácí motivace, zaměstnanci přestávají komunikovat a dříve fungující tým se rozpadá na skupinu solitérů? Odborníci na personalistiku dali dohromady několik rad, jak udržet tým v chodu, i když pracovní podmínky nejsou ideální.

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý