Algoritmer og datastrukturer

Jeg antar at du er en dataprogrammerer. Kanskje du er en ny student innen datavitenskap, eller kanskje du er en erfaren programvareingeniør. Uansett hvor du er på det spekteret, algoritmer og datastrukturer saken. Ikke bare som teoretiske begreper, men som byggeklosser som brukes til å skape løsninger på forretningsproblemer.

Sikker på at du kanskje vet hvordan du bruker c # Liste eller Stable klasse, men forstår du hva som skjer under dekslene? Hvis ikke, gjør du virkelig de beste beslutningene om hvilke algoritmer og datastrukturer du bruker?

Betydende forståelse av algoritmer og datastrukturer begynner med å ha en måte å uttrykke og sammenligne deres relative kostnader.

Asymptotisk analyse

Når vi snakker om å måle kostnaden eller kompleksiteten til en algoritme, er det vi snakker om, å utføre en analyse av algoritmen når inngangssettene er svært store. Analysere hva som skjer etter hvert som antall innganger blir svært store refereres til som asymptotisk analyse. Hvordan endrer kompleksiteten til algoritmen når den brukes på ti, eller tusen eller ti millioner elementer? Hvis en algoritme går i fem millisekunder med tusen elementer, hva kan vi si om hva som vil skje når det går med en million? Vil det ta fem sekunder eller fem år? Ville du heller ikke finne ut dette før kunden din?

Dette er viktig!

Vekstraten

Vekstraten beskriver hvordan en algoritmens kompleksitet endres etter hvert som inngangsstørrelsen vokser. Dette er vanligvis representert ved hjelp av Big-O notasjon. Big-O notasjon bruker en hovedstad O ("rekkefølge") og en formel som uttrykker kompleksiteten til algoritmen. Formelen kan ha en variabel, n, som representerer størrelsen på inngangen. Følgende er noen vanlige ordrefunksjoner vi vil se i denne boken, men denne listen er på ingen måte fullført.

Konstant - O (1)

En O (1) algoritme er en hvis kompleksitet er konstant uansett hvor stor inngangsstørrelsen er. "1" betyr ikke at det bare er en operasjon, eller at operasjonen tar litt tid. Det kan ta en mikrosekund, eller det kan ta en time. Poenget er at størrelsen på inngangen ikke påvirker tiden operasjonen tar.

offentlig int GetCount (int [] elementer) return items.Length;  

Lineær - O (n)

En O (n) algoritme er en hvis kompleksitet vokser lineært med størrelsen på inngangen. Det er rimelig å forvente at hvis en inngangsstørrelse på en tar fem millisekunder, vil en innspilling med tusen elementer ta fem sekunder.

Du kan ofte kjenne igjen en O (n) -algoritme ved å lete etter en loopingsmekanisme som gir tilgang til hvert medlem.

offentlig lang GetSum (int [] elementer) lang sum = 0; foreach (int jeg i elementer) sum + = i;  returbeløp;  

Logaritmisk - O (log n)

En O (log n) algoritme er en hvis kompleksitet er logaritmisk til sin størrelse. Mange deler og overvinne algoritmer faller inn i denne bøtte. Det binære søketreet inneholder Metoden implementerer en O (log n) algoritme.

Linearitmisk - O (n log n)

En linearithmisk algoritme, eller loglinear, er en algoritme som har en kompleksitet av O (n log n). Noen deler og erobrer algoritmer faller inn i denne bøtte. Vi ser to eksempler når vi ser på flette sortering og rask sortering.

Kvadratisk - O (n ^ 2)

En O (n ^ 2) algoritme er en hvis kompleksitet er kvadratisk til sin størrelse. Selv om det ikke alltid er unødvendig å bruke en kvadratisk algoritme, er det et potensielt tegn på at du må revurdere algoritmen eller datastrukturen. Kvadratiske algoritmer skaleres ikke godt når innstørrelsen vokser. For eksempel vil en matrise med 1000 heltall kreve at 1.000.000 operasjoner skal fullføres. En innsats med en million elementer vil ta en trillion (1.000.000.000.000) operasjoner. For å sette dette i perspektiv, hvis hver operasjon tar en millisekund å fullføre, vil en O (n ^ 2) -algoritme som mottar en innspilling på en million elementer, ta nesten 32 år å fullføre. Å gjøre den algoritmen 100 ganger raskere vil fortsatt ta 84 dager.

Vi ser et eksempel på en kvadratisk algoritme når vi ser på bubblesort.

Beste, gjennomsnittlig og verste tilfelle

Når vi sier en algoritme er O (n), hva sier vi egentlig? Sier vi at algoritmen er O (n) i gjennomsnitt? Eller beskriver vi det beste eller verste fallet?

Vi betyr vanligvis det verste fallet, med mindre det vanlige saken og verste fallet er svært forskjellige. For eksempel vil vi se eksempler i denne boken hvor en algoritme er O (1) i gjennomsnitt, men blir periodisk O (n) (se ArrayList.Add). I disse tilfellene vil jeg beskrive algoritmen som O (1) i gjennomsnitt og deretter forklare når kompleksiteten endres.

Hovedpunktet er at å si O (n) betyr ikke at det alltid er n operasjoner. Det kan være mindre, men det bør ikke være mer.

Hva måler vi??

Når vi måler algoritmer og datastrukturer, snakker vi vanligvis om en av to ting: hvor lang tid operasjonen tar for å fullføre (operativ kompleksitet), eller mengden ressurser (minne) som en algoritme bruker (ressurskompleksitet).

En algoritme som går ti ganger raskere, men bruker ti ganger så mye minne, kan være helt akseptabelt i et servermiljø med store mengder tilgjengelig minne, men kan ikke være hensiktsmessig i et innebygd miljø hvor tilgjengelig minne er svært begrenset.

I denne boken vil jeg først og fremst fokusere på operativ kompleksitet, men i avsnittet Sorteringsalgoritmer ser vi noen eksempler på ressurskompleksitet.

Noen konkrete eksempler på ting vi kan måle inkluderer:

  • Sammenlikningsoperasjoner (større enn mindre enn, lik).
  • Oppdrag og datautveksling.
  • Minneallokeringer.

Konteksten til operasjonen som utføres vil typisk fortelle deg hvilken type måling som gjøres.

For eksempel, når vi diskuterer kompleksiteten til en algoritme som søker etter et element i en datastruktur, snakker vi nesten helt sikkert om sammenligningsoperasjoner. Søk er generelt en skrivebeskyttet operasjon, så det bør ikke være nødvendig å utføre oppgaver eller tildele minne.

Men når vi snakker om datasortering, kan det være logisk å anta at vi kunne snakke om sammenligninger, oppgaver eller tildelinger. I tilfeller der det kan være tvetydighet, vil jeg angi hvilken type måling kompleksiteten faktisk refererer til.

Neste

Dette fullfører den første delen om algoritmer og datastrukturer. Deretter fortsetter vi videre til den koblede listen.