Kalo te përmbajtja

8 min lexim

American Corners

Big-O: si matet rritja e kodit

Dy programe, një përgjigje, shpejtësi krejt të ndryshme

Deri tani, nëse një program jepte përgjigjen e saktë, mjaftonte. Kjo ndryshon në çastin që të dhënat bëhen të mëdha. Dy programe mund të pajtohen për çdo përgjigje dhe prapë të jenë larg njëri-tjetrit: njëri mbaron menjëherë me një milion njësi, tjetri ende po punon kur ti ke ikur në shtëpi.

Pyetja që i përgjigjet ky mësim nuk është "sa sekonda i duhen?" Një laptop më i shpejtë i ndryshon sekondat, por jo sjelljen e brendshme. Pyetja e vërtetë është: ndërsa hyrja rritet, si rritet me të sasia e punës? Ajo formë e rritjes është ajo që masim, dhe Big-O është shënimi me të cilin e shkruajmë.

Numëro punën, jo orën

Të matësh një program me kronometër është i pabesueshëm. Numri varet nga makina jote, nga çfarë tjetër po ekzekuton, madje nga sa i ngrohtë është procesori. Ndaj, në vend që të masim kohën, numërojmë hapat që bën programi si funksion i madhësisë së hyrjes, të cilën e quajmë n.

Shiko këto dy cikle mbi një listë me n njësi:

# Cikli A: shiko çdo njësi një herë
for item in data:
    print(item)

# Cikli B: për çdo njësi, shiko sërish çdo njësi
for a in data:
    for b in data:
        print(a, b)

Cikli A bën n shtypje. Cikli B bën n shtypje për secilën nga n njësitë, pra n * n = n² shtypje. Në një listë me 10 kjo është 10 kundrejt 100. Në një listë me 1000 është 1000 kundrejt 1,000,000. E njëjta ide, punë tejet e ndryshme. Ndërthurja është shenja: një cikël brenda një cikli zakonisht e kthen n.

Big-O: forma e rritjes

Big-O e mban vetëm pjesën që ka rëndësi kur n bëhet i madh, dhe i heq konstantet e termat e vegjël. Nuk themi "rreth 3n plus 7 hapa"; themi se rritja është O(n). Tri forma mbulojnë shumicën e asaj që has një fillestar:

  • O(1), konstante. Puna nuk rritet fare me n. Leximi i data[0] ose len(data) merr të njëjtën kohë, qoftë lista me dhjetë njësi apo dhjetë milionë.
  • O(n), lineare. Puna rritet krah për krah me n. Një kalim mbi të dhënat, si Cikli A. Dyfisho të dhënat, dyfishohet puna.
  • O(n²), kuadratike. Puna rritet me katrorin e n. Një cikël brenda një cikli, si Cikli B. Dyfisho të dhënat, katërfishohet puna.

Këshillë

Mënyra më e shpejtë për të hamendësuar Big-O-në e një funksioni është të numërosh ciklet e ndërthurura mbi të dhënat. Pa cikël mbi hyrjen është shpesh O(1). Një cikël është zakonisht O(n). Një cikël brenda një cikli është zakonisht O(n²). Është rregull praktik, jo ligj, por i kap shumicën e rasteve.

Një shembull i punuar: a ka dublikate?

Le të themi se ke një listë numrash identifikimi të nxënësve dhe do të dish nëse ndonjë numër shfaqet dy herë. Ja përpjekja e parë e natyrshme: krahaso çdo njësi me çdo njësi që vjen pas saj.

def has_duplicate_slow(ids):
    for i in range(len(ids)):
        for j in range(i + 1, len(ids)):
            if ids[i] == ids[j]:
                return True
    return False

Funksionon, por është një cikël brenda një cikli, ndaj është O(n²). Në një klasë me 30 nxënës nuk është asgjë. Në një bazë kombëtare me një milion numra janë një trilion krahasime, dhe do të presësh shumë gjatë.

Tani përdor një vegël që e ke takuar tashmë, një set (bashkësi), që mund të kontrollojë përkatësinë thuajse menjëherë:

def has_duplicate_fast(ids):
    seen = set()
    for one in ids:
        if one in seen:
            return True
        seen.add(one)
    return False

Kjo bën një kalim të vetëm mbi listën, dhe çdo kontroll in mbi një set është afërsisht O(1), ndaj i gjithë funksioni është O(n). E njëjta përgjigje si versioni i ngadaltë, por me një milion numra mbaron sa hap e mbyll sytë. Mësimi nuk është "set-et janë magji"; është se zgjedhja e strukturës së duhur të të dhënave e ndryshoi formën e rritjes, nga poshtë te n.

Ai këmbim ka një kosto që ia vlen ta emërtojmë: versioni i shpejtë mban një set seen, ndaj përdor më shumë memorie për të kursyer kohë. Big-O e përshkruan edhe rritjen e memories, dhe këmbimi i kohës me hapësirën është një nga vendimet më të shpeshta që do të marrësh si programues.

Tërhiq rrëshqitësin për të parë si ndahen dy kontrolluesit e dublikateve: versioni me cikle të ndërthurura ngjitet si , ndërsa versioni me set rritet vetëm me n.

Gara Big-O: n² kundrejt n

Cikle të ndërthururaO(n²)

400 veprime

Me set (bashkësi)O(n)

20 veprime

Me n = 20, ciklet e ndërthurura bëjnë 400 veprime, ndërsa set-i bën 20 · pra 20× më shumë punë.

Ku pushon së qeni i besueshëm ky model

Big-O është model i dobishëm dhe, si çdo model i dobishëm, është thjeshtim. Tri vende ku pushon së qeni i besueshëm:

  • I hedh tej konstantet. Një qasje O(n) me një hap të shtrenjtë mund të humbasë kundër një qasjeje O(n në katror) me hap të lirë, derisa n të bëhet i madh. Big-O të thotë cila fiton në fund, jo cila fiton sot.
  • O(1) këtu do të thotë "mesatarisht". Kërkimi në një bashkësi është i shpejtë në rastin e zakonshëm, jo i garantuar të jetë një hap çdo herë.
  • n i vogël është rast i vërtetë, jo gabim rrumbullakimi. Me dymbëdhjetë emra, kodi më i thjeshtë që lexohet me një vështrim është zakonisht përgjigjja e duhur inxhinierike.

Përdore Big-O për të krahasuar format e rritjes. Mos e përdor për të shpallur fituesin pa ditur sa të mëdha bëhen vërtet të dhënat.

Provo veten

  1. Pse e masim rritjen e punës ndërsa n rritet, në vend që thjesht ta masim programin në sekonda te kompjuteri ynë?
  2. Një funksion ka një cikël for të vetëm mbi një listë me n njësi, pa cikël brenda tij. Cila është Big-O e tij, dhe çfarë i ndodh punës kur lista dyfishohet?
  3. Kontrolli i shpejtë i dublikateve është O(n) por përdor memorie shtesë për set-in seen, ndërsa i ngadalti është O(n²) por nuk përdor thuajse fare. Përshkruaj një situatë ku prapë mund të zgjidhje versionin më të ngadaltë.

Nga vjen ky mësim

Ndërtuar mbi

  • Data Structures and Algorithms: seanca për efikasitetin dhe kompleksitetin
  • Për të lexuar më tej: Brian Heinold, A Practical Introduction to Python Programming

Kurset e alphaPlan ndërtohen mbi programe të zhvilluara në klasë, e nuk shpiken për web-in. Kur një pohim mbështetet mbi një standard të jashtëm ose mbi një rast të raportuar, ai emërtohet më sipër që ta kontrollosh vetë e të mos na besosh në fjalë.

Ky kurs u zhvillua nga alphaPlan Center mbi bazën e programeve të realizuara në partneritet me rrjetin American Corners.

Gjete diçka të paqartë, të vjetruar ose që mund të përmirësohet? Sugjero një përmirësim