logo
Notasjon
Algoritmer og datastrukturer
IT, Høgskolen i Østfold
AlgDat 12 > Emner > Algoritmer > Notasjon

Notasjon

Det er i hovedsak to måter å beskrive algoritmer som skal utføres av en datamaskin:

  1. Med "fri" tekst, ofte kalt pseudokode eller kvasikode
  2. I et formelt definert programmerings- eller beskrivelsesspråk, f.eks. Java eller IDL (eksakt kode)
Hva man bruker, er avhengig av formålet. Med pseudokode kan det være lettere å få fram store linjer der hvor eksakt kode blir for detaljert. Faren med pseudokode er at det blir for lite nøyaktig, og det er lett å introdusere tvetydigheter. I det virkelige liv brukes ofte en kombinasjon av de to beskrivelsesteknikkene.

Vi skal nå se på noen generelle retningslinjer for gode algoritmebeskrivelser.

Generelle elementer

En algoritmebeskrivelse bør inneholder stort sett disse elementene:

Input
Mange algoritmer er avhengig av å bli servert et materiale de skal bearbeide.
Euklids algoritme: To heltall A og B.
Output
Hvis en algoritme skal levere fra seg et resultat, må dette spesifiseres.
Euklids algoritme: Et heltall.
Lokale variabler
Som oftest trenger man lokale variabler, og disse må beskrives med type og navn.
Euklids algoritme: To heltall TMP og D.
Tilordninger
Innholdet i variablene endres ved tilordninger.
Euklids algoritme: I steg 4 får D en ny verdi, og i steg 5 settes så A til verdien av D.
Funksjonskall
I følge god programmeringsskikk brytes kompliserte problemer ned til et sett av enklere prosedyrer eller funksjoner. Derfor vil de fleste algoritmer benytte seg av slike "hjelperutiner" som typisk er beskrevet for seg.
Euklids algoritme: Vi kunne godt ha formulerte steg 4 som et funksjonkall. f.eks.:
   4. Sett D til mod(A, B)
		
der mod(A, B) er en funksjon som regner ut restverdien vi får ved dele A med B (A modulo B).
Logiske tester
Algoritmer er helt avhengige av logiske tester, f.eks. for å kunne stoppe algoritmen når vi har kommet fram til en løsning.
Euklids algoritme: I steg 3 spør man om B er lik null, og hvis det er tilfelle går vi ut av gjennomføringsdelen.
Løkker
De fleste algoritmer kunne ikke formuleres uten forskjellige former for løkker. Løkkene gjør at en sekvens av steg utføres flere ganger. I hver iterasjon blir typisk nye verdier for en eller flere variablr beregnet.
Euklids algoritme: Løkka består av trinnene 2 til 6, og er beskrevet ved hjelp av en "gå-til" mekanisme.

Kommentarer

I de fleste tilfeller bør man bruke kommentarer som i vanlige ordelag forklarer hva som skjer. En god vane kan være å først skrive ned algoritmen i kommentarform, uansett om man skal formulere den i pseudokode eller eksakt kode.

Euklids algoritme kunne f.eks. uttrykkes slik på kommentarnivå:

	1   // Hent inn to heltall
	2   // Gå i løkke:
		   // Hvis det minste tallet er 0 returnes det største som løsningen
		   // Del det største tallet på det minste,
		   // og ta vare på restverdien og det minste tallet
		   // Gjør en iterasjon til med de nye tallene
	3   // Avslutt

Man må på en eller annen måte markere at det er kommentarer det er snakk om. Her er det brukt "//" som er vanlig i f.eks. Java og C++, men man kan jo bruke hva som helst bare man er konsistent og alltid bruker samme notasjon.

Pseudokode

Det finnes utrolig mange ulike måter å skrive pseudokode på. Det viktigste er at man prøver å være så utvetydig og eksakt som mulig. Det er dermed viktig notasjonen blir brukt på en konsistent måte. Notasjonen må som et minimum omfatte standardelementene i en algoritme.

Euklids algoritme ble beskrevet på en vanlig forekommende og greit forståelig form for pseudokode. Merk at den hierarkiske nummereringen gjør det lett å se f.eks. løkker og blokker i logiske tester.

Her kommer nok en variant av Euklids Algoritme. Vi definerer først en rutine som sørger for at to heltall kommer i stigende rekkefølge (OBS: Her antar vi at input kommer som referanser, se Java).

OrdneHeltall _____________________________________________ Input: Heltall A, Heltall B Output: Heltall A, Heltall B 1 Hvis A er mindre enn B: 1.1 Sett et heltall TMP lik A 1.2 Sett A lik B 1.3 Sett B lik TMP 2 Stopp

Deretter formulerer vi SFF-funksjonen:

StørsteFellesFaktor _____________________________________________ Input: Heltall A, Heltall B Output: Heltall 1 OrdneHeltall(A, B) 2 Så lenge B er større enn 0 2.1 Sett A lik A modulo B 2.2 OrdneHeltall(A, B) 3 Returner A

Merk at dette ikke er den eneste måten å skrive pseudokode på, men et eksempel på hvordan det kan gjøres på en eksakt og konsistent måte, og som dekker de vikigste elementene i en algoritme.

Eksakt kode

Eksakt kode bør være mer eller mindre kompilerbar. Vi ser først på en versjon blandet med pseudokode. Det er hensiktsmessig å skille ut pseudokoden fra den eksakte koden, f.eks. ved å sette den mellom '<' og '>'. Pass på å ikke blande sammen pseudokode og kommentarer.

... public int SFF(int A, int B) { // Sørger for at A er størst < Hvis A er mindre enn B: Bytt om A og B > // Gå i løkke helt til B blir null // I hver iterasjon setter vi A lik restverdien vi får ved å dele A på B while (B > 0) { // Finner restverdien < A settes til A modulo B > // Sørger for at A er størst hele tiden } // B er blitt null, og da er A løsningen. Magic :-) return A; } ....
java

Da gjenstår det bare å bytte ut pseudokoden med eksakt kode, og vi har en kjørbar og korrekt (håper vi) algoritme:

... public int SFF(int A, int B) { if (A < B) { int TMP = A; A = B; B = TMP; } while (B > 0) { A = A % B; if (A < B) { int TMP = A; A = B; B = TMP; } } return A; } ....

Gunnar Misund, 13.jun.2012