Vadovėlis/Paieška ir Rikiavimas: Skirtumas tarp puslapio versijų

Iš Pitonas.
S (ArturasNik perkėlė puslapį Vadovėlis/Paieška į Vadovėlis/Paieška ir Rikiavimas be nukreipimo)
Nėra keitimo santraukos
1 eilutė: 1 eilutė:
Dvejetainė paieška yra algoritmas, skirtas rasti reikiamą elementą surikiuotame sąraše. Algoritmas dirba tik su surikiuotais sąrašais, todėl jis yra veiksmingas, kai reikia rasti tam tikrą elementą dideliame sąraše.
Atlikęs praeito skyriaus uždavinius, jau žinai daug apie sąrašo sukūrimą ir visus bazinius sąrašo metodus. Dabar pasinaudosim įgytomis žiniomis ir susipažinsim su labai dažnai susidruriamais uždaviniais: paieška ir rikiavimas.


Trumpiausio kelio algoritmas yra algoritmas, skirtas rasti trumpiausią kelią tarp dviejų taškų grafuose su svorių viršūnių.
Paieškos algoritmai naudojami norint rasti konkretų elementą sąraše ar duomenų masyve. Yra keletas paieškos algoritmų, tačiau parodysiu du dažniausiai naudojaus - tiesinė paieška ir dvejetainė paieška.


Euristinis algoritmas yra algoritmas, kuris apskaičiuoja artimiausią sprendimą be visiško sprendimo suradimo. Šis algoritmas gali būti naudingas sudėtingų problemų sprendime, kai yra per daug galimų sprendimų ir pilnas suradimas užima per daug laiko.
== Tiesinė paieška ==
Tiesinė paieška - tai paprastas paieškos algoritmas, kuris, ieškodamas tikslinės reikšmės, peržiūri kiekvieną sąrašo elementą. Pažiūrėk į tiesinės paieškos funkcijos pavyzdį "Python" kalba:


Štai kaip galite panaudoti dvejetainės paieškos algoritmą Python kalboje:
<syntaxhighlight lang="python">
def tiesinė_paieška(sąrašas, ieškomas_žodis):
    for i in range(len(sąrašas)):
        if sąrašas[i] == ieškomas_žodis:
            return i
    return -1  # ieškomas_žodis nerastas
</syntaxhighlight>
 
Ši funkcija priima masyvą <code>sąrašas</code> ir tikslinę reikšmę <code>ieškomas_žodis</code> ir grąžina tikslinės reikšmės indeksą masyve. Jei tikslinė vertė nerandama masyve, funkcija grąžina -1. Labai praprasta ir aišku.
 
== Dvejetainė paieška ==
Kita vertus, dvejetainė paieška yra efektyvesnis paieškos algoritmas, kuris veikia tik rūšiuotuose masyvuose. Jis veikia pakartotinai dalydamas paieškos intervalą per pusę, kol randama tikslinė reikšmė. Painu? Daug aiškiau bus pažiūrėjus šį pavyzdį:


<syntaxhighlight lang="python">
<syntaxhighlight lang="python">
def devetainė_paieška(sąrašas, ieškomas_elementas):
def dvejetainė_paieška(sąrašas, tikslas):
     kairė, dešinė = 0, len(sąrašas)-1
     # išsisaugom sąrašo pirmą ir paskutinį indeksą
     while kairė <= dešinė:
    apačia = 0
         vidurys = (kairė+dešinė) // 2
    viršus = len(sąrašas) - 1
         if sąrašas[vidurys] == ieškomas_elementas:
   
             return vidurys
     while apačia <= viršus:
         elif sąrašas[vidurys] < ieškomas_elementas:
        # aatrandame vidurį pagal formulę: (pradžios indeksas + pabaigos indeksas) padalintas per pusę, be liekanos
             kairė = vidurys + 1
         viduriukas = (apačia + viršus) // 2
        # patikriname, ar `viduriukas` indekse yra mūsų ieškomas tikslas, ir jį atradus grąžiname indeksą.
         if sąrašas[viduriukas] == tikslas:
             return viduriukas
        # jeigu ne, tai pagal tai, kurioje pusėje yra ieškomas elementas pakeičiame viršutinį arba apatinį indeksą
         elif sąrašas[viduriukas] < tikslas:
             apačia = viduriukas + 1
         else:
         else:
             dešinė = vidurys - 1
             viršus = viduriukas - 1
     return -1
        # ir kartojame iš naujo, bet jau su nauju, per pus mažesniu rėžiu
   
     return -1 # tikslas nerastas
 
sąrašas = [1,2,3,4,5,6,7,8,9,10]
print(dvejetainė_paieška(sąrašas, 7)) # 6
</syntaxhighlight>
</syntaxhighlight>
Panagrinėkim detaliai, kaip vyksta procesas. Ieškome, kur yra skaičius 7, sąraše [1,2,3,4,5,6,7,8,9,10]. Funkcijos pradžios kintamieji:
apačia = 0
viršus = 9 (ilgis 10 - 1 )
Pirmas `while` ciklas:
viduriukas = 4 # (0 + 9) // 2
sąrašas[4] saugo reikšmę 5. Ne mūsų ieškomas skaičius.
kadangi tikslas yra surasti 7, tai mūsų kito ciklo metu ieškosime viršutinėje sąrašo dalyje, todėl nusistatome naują apačios reikšmę, viduriukas + 1.
apačia = 4 + 1 = 5.
Antras `while` ciklas:
viduriukas = 7 # (5 + 9) // 2
sąrašas[7] saugo reikšmę 8. Jau arčiau, bet ne dar vis ne mūsų ieškoma reikšmė 7. Nustatome šįkartą naują viršutinę reikšmę, viduriukas - 1
viršus = 7 - 1 = 6
Trečias `while` ciklas:
viduriukas = 5 # (5 + 6) // 2
sąrašas[5] saugo reikmę 6. Vėl pro šalį. Nustatome naują apatinę reikšmę:
apačia = 5 + 1 = 6
Ketvirtas `while` ciklas:
viduriukas = 6 # (6 + 6) // 2
sąrašas[6] saugo reikšmę 7. Valio! Radom. Grąžinam indeksą 7.
Atkreipk dėmesį, kad dvejetainės paieškos algoritmas atrado reikšmę per 4 ciklus. Kaip manai, kiek ciklų prireiktų tiesinės paieškos algoritmui? Pasufleruosiu... Daugiau :)
== Rikiavimas ==

19:49, 4 gegužės 2023 versija

Atlikęs praeito skyriaus uždavinius, jau žinai daug apie sąrašo sukūrimą ir visus bazinius sąrašo metodus. Dabar pasinaudosim įgytomis žiniomis ir susipažinsim su labai dažnai susidruriamais uždaviniais: paieška ir rikiavimas.

Paieškos algoritmai naudojami norint rasti konkretų elementą sąraše ar duomenų masyve. Yra keletas paieškos algoritmų, tačiau parodysiu du dažniausiai naudojaus - tiesinė paieška ir dvejetainė paieška.

Tiesinė paieška

Tiesinė paieška - tai paprastas paieškos algoritmas, kuris, ieškodamas tikslinės reikšmės, peržiūri kiekvieną sąrašo elementą. Pažiūrėk į tiesinės paieškos funkcijos pavyzdį "Python" kalba:

def tiesinė_paieška(sąrašas, ieškomas_žodis):
    for i in range(len(sąrašas)):
        if sąrašas[i] == ieškomas_žodis:
            return i
    return -1  # ieškomas_žodis nerastas

Ši funkcija priima masyvą sąrašas ir tikslinę reikšmę ieškomas_žodis ir grąžina tikslinės reikšmės indeksą masyve. Jei tikslinė vertė nerandama masyve, funkcija grąžina -1. Labai praprasta ir aišku.

Dvejetainė paieška

Kita vertus, dvejetainė paieška yra efektyvesnis paieškos algoritmas, kuris veikia tik rūšiuotuose masyvuose. Jis veikia pakartotinai dalydamas paieškos intervalą per pusę, kol randama tikslinė reikšmė. Painu? Daug aiškiau bus pažiūrėjus šį pavyzdį:

def dvejetainė_paieška(sąrašas, tikslas):
    # išsisaugom sąrašo pirmą ir paskutinį indeksą
    apačia = 0
    viršus = len(sąrašas) - 1
    
    while apačia <= viršus:
        # aatrandame vidurį pagal formulę: (pradžios indeksas + pabaigos indeksas) padalintas per pusę, be liekanos
        viduriukas = (apačia + viršus) // 2
        # patikriname, ar `viduriukas` indekse yra mūsų ieškomas tikslas, ir jį atradus grąžiname indeksą.
        if sąrašas[viduriukas] == tikslas:
            return viduriukas
        # jeigu ne, tai pagal tai, kurioje pusėje yra ieškomas elementas pakeičiame viršutinį arba apatinį indeksą
        elif sąrašas[viduriukas] < tikslas:
            apačia = viduriukas + 1
        else:
            viršus = viduriukas - 1
        # ir kartojame iš naujo, bet jau su nauju, per pus mažesniu rėžiu
    
    return -1  # tikslas nerastas

sąrašas = [1,2,3,4,5,6,7,8,9,10]
print(dvejetainė_paieška(sąrašas, 7)) # 6

Panagrinėkim detaliai, kaip vyksta procesas. Ieškome, kur yra skaičius 7, sąraše [1,2,3,4,5,6,7,8,9,10]. Funkcijos pradžios kintamieji:

apačia = 0
viršus = 9 (ilgis 10 - 1 )

Pirmas `while` ciklas:

viduriukas = 4 # (0 + 9) // 2
sąrašas[4] saugo reikšmę 5. Ne mūsų ieškomas skaičius.
kadangi tikslas yra surasti 7, tai mūsų kito ciklo metu ieškosime viršutinėje sąrašo dalyje, todėl nusistatome naują apačios reikšmę, viduriukas + 1.
apačia = 4 + 1 = 5.

Antras `while` ciklas:

viduriukas = 7 # (5 + 9) // 2
sąrašas[7] saugo reikšmę 8. Jau arčiau, bet ne dar vis ne mūsų ieškoma reikšmė 7. Nustatome šįkartą naują viršutinę reikšmę, viduriukas - 1
viršus = 7 - 1 = 6

Trečias `while` ciklas:

viduriukas = 5 # (5 + 6) // 2
sąrašas[5] saugo reikmę 6. Vėl pro šalį. Nustatome naują apatinę reikšmę:
apačia = 5 + 1 = 6

Ketvirtas `while` ciklas:

viduriukas = 6 # (6 + 6) // 2
sąrašas[6] saugo reikšmę 7. Valio! Radom. Grąžinam indeksą 7.

Atkreipk dėmesį, kad dvejetainės paieškos algoritmas atrado reikšmę per 4 ciklus. Kaip manai, kiek ciklų prireiktų tiesinės paieškos algoritmui? Pasufleruosiu... Daugiau :)

Rikiavimas