29.07.2013 Views

Abstrakte datatyper – C#-version

Abstrakte datatyper – C#-version

Abstrakte datatyper – C#-version

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

NOEA/IT <strong>–</strong> Programmeringsteknologi/<strong>C#</strong>.NET FEN/2004-02-20<br />

Note til Programmeringsteknologi<br />

Akademiuddannelsen i Informationsteknologi<br />

<strong>Abstrakte</strong> <strong>datatyper</strong> <strong>–</strong> <strong>C#</strong>-<strong>version</strong><br />

Finn Nordbjerg<br />

1/9


NOEA/IT <strong>–</strong> Programmeringsteknologi/<strong>C#</strong>.NET FEN/2004-02-20<br />

<strong>Abstrakte</strong> Datatyper<br />

Denne note introducerer kort begrebet abstrakt datatype (ADT) og beskriver den abstrakte<br />

datatype sekvens eller (ordnet) liste.<br />

Datastrukturer<br />

En datastruktur er en systematisk måde at organisere en mængde af data på. Datastrukturer kan<br />

være persistente, dvs. lagret på disk eller interne, dvs. lagret i memory. Vi betragter her kun<br />

interne datastrukturer. Endvidere skelner man mellem statiske og dynamiske datastrukturer. En<br />

statisk datastruktur har en fast størrelse under hele programafviklingen, mens en dynamisk<br />

datastruktur kan ændre størrelse efter behov under programudførelsen.<br />

En datastruktur er en fysisk organisering af en datamængde.<br />

Klassiske datastrukturer er bl.a.:<br />

• Array <strong>–</strong> statisk<br />

• Kædet liste <strong>–</strong> dynamisk<br />

• Træstruktur <strong>–</strong> oftest dynamisk<br />

• Hashtabel <strong>–</strong> kan være statisk eller dynamisk<br />

Vi ser i første omgang kun på arrays. Et array er et sammenhængende segment af memory, hvor<br />

elementerne er indekserede, dvs. kan tilgås udfra deres position. Elementerne er af samme type.<br />

Datastrukturer har brug for en række algoritmer til indsættelse, sletning, søgning af data. En<br />

datastruktur samt algoritmer til at operere på dataene er en realisering af en abstrakt datatype.<br />

Datatyper<br />

Generelt er en datatype givet ved en værdimængde og et sæt af tilhørende operationer. Endvidere<br />

er der behov for en datastruktur til at repræsentere datatypens værdimængde:<br />

• Værdimængde (Hvilke værdier kan typen indeholde?)<br />

• Operationer (Hvilke operationer er lovlige at udføre på elementer af<br />

datatypen?)<br />

• Datarepræsentation (Hvordan repræsenteres datatypen i hukommelsen)<br />

2/9


NOEA/IT <strong>–</strong> Programmeringsteknologi/<strong>C#</strong>.NET FEN/2004-02-20<br />

Alle programmeringssprog tilbyder indbyggede <strong>datatyper</strong> <strong>–</strong> værdier, datarepræsentation og<br />

lovlige operationer defineres af sproget. Fx. har <strong>C#</strong> indbygget standardtyper som bool med<br />

værdierne true og false, og operationer som and (”&&”), or (”||”) og not (”!”) <strong>–</strong> de såkaldte<br />

logiske operationer. Denne type anvendes meget i forbindelse med programmering af<br />

kontrolstrukturer (selektioner og iterationer). En anden standardtype er int, hvis værdier er heltal,<br />

og operationerne er regneoperationer, sammenligninger mm. Alle variable erklæres af<br />

programmøren som tilhørende en type (som regel ikke i Scriptsprog). Compileren til de fleste<br />

sprog undersøger, at man kun bruger lovlige operationer.<br />

Udover de indbyggede typer giver <strong>C#</strong> mulighed for, at man kan definere sine egne typer. Disse<br />

typer kaldes ofte abstrakte <strong>datatyper</strong>.<br />

En vigtig gruppe adt’er er de såkaldte Collections, som indkapsler en datastruktur. Formålet<br />

hermed er, at skjule datastrukturens implementation, så denne kan ændres, uden at det påvirker<br />

resten af systemet. Man opnår det, der kaldes dataabstraktion.<br />

Sagt på en anden måde, så adskiller man hvad fra hvordan. Nedenstående figur (fra Carrano ea.:<br />

Data Abstraction and Problem Solving with Java, Addison-Wesley) illustrerer princippet:<br />

Figure 3.7<br />

ADT operations provide access to a data structure<br />

adt<br />

Datastruktur+<br />

algoritmer<br />

3/9


NOEA/IT <strong>–</strong> Programmeringsteknologi/<strong>C#</strong>.NET FEN/2004-02-20<br />

Princippet er, at programmer kan anvende adt’en alene udfra kendskab til operationernes<br />

specifikationer. Man behøver altså ikke at bekymre sig datastrukturen og de algoritmer, som<br />

realiserer operationerne på datastrukturen.<br />

ADT’en sekvens<br />

En meget udbredt adt er sekvens eller ordnet liste <strong>–</strong> ofte blot liste. Den findes i de fleste moderne<br />

programmeringssprogs bibliotek, således også i <strong>C#</strong>, hvor den hedder Ilist, og har en realisering,<br />

som hedder ArrayList.<br />

En sekvens er en samling af værdier, som står i en eller anden rækkefølge. Man kan altså tale om<br />

første værdi, sidste værdi eller syvende værdi. Ligeledes er det muligt at indsætte og slette<br />

værdier på en bestemt plads. Praktiske varianter af sekvenser er utallige, fx. en sekvens af<br />

studerende ved et erhvervsakademi, en sekvens af bøger i et bibliotek, en sekvens af tegn (kaldes<br />

ofte en streng) i et program, der arbejder med tekster. Vi vil i første omgang koncentrere os om<br />

et simpelt eksempel, nemlig sekvenser af heltal. Vi har kaldt typen SeqInt.<br />

Værdimængden for SeqInt<br />

Værdimængden for datatypen SeqInt er følger af heltal. Her er en række forskellige eksempler:<br />

[1, 3, 5]<br />

[1, 5, 3]<br />

[-1, 34, 56]<br />

[1]<br />

[2, 65, 8, 999, 434, 0, 12, 1, -5, 78, 9]<br />

[] (en tom sekvens, men dog stadig en sekvens).<br />

Elementerne i en sekvens refereres via deres index. Første element har index 0.<br />

I det følgende vil vi realisere SeqInt vha. <strong>C#</strong>’s ArrayList:<br />

Operationer på ArrayList<br />

Følgende operationer kan udføres på en variabel s af typen ArrayList:<br />

Definerer en sekvens s.<br />

Nulstiller s.<br />

ArrayList s= new ArrayList();<br />

s.Clear();<br />

4/9


NOEA/IT <strong>–</strong> Programmeringsteknologi/<strong>C#</strong>.NET FEN/2004-02-20<br />

s.Insert(i,e);<br />

Indsætter elementet e på pladsen med index i og rykker eventuelle efterfølgende elementer.<br />

s.RemoveAt(i);<br />

Fjerner elementet med index i og rykker eventuelle efterfølgende elementer tilbage.<br />

s.Add(e);<br />

Tilføjer elementet e som det sidste element.<br />

Udover disse operationer, som er implementeret som metoder, har ArrayList et par operationer<br />

mere:<br />

s.Count;<br />

Returnerer en int indeholdende antallet af elementer i s.<br />

s[i]<br />

tilgår det i’te element, således at<br />

int x= s[i];<br />

placerer værdien af det i’te element i x, og<br />

s[i]= x;<br />

ændrer værdien af det i’te element til x.<br />

Det skal slutteligt nævnes, at ArrayList har en lang række andre operationer, som vi ikke vil<br />

fordybe os i her. Se dokumentationen.<br />

Eksempel på brug af SeqInt<br />

På næste side ses et lille program, som opretter en SeqInt, sætter nogle tal ind i sekvensen,<br />

udskriver sekvensen, bruger et par operationer og udskriver sekvensen igen.<br />

5/9


NOEA/IT <strong>–</strong> Programmeringsteknologi/<strong>C#</strong>.NET FEN/2004-02-20<br />

using System;<br />

using System.Collections;<br />

class TestSeqInt<br />

{<br />

private static ArrayList sekvens = new ArrayList();<br />

static void Main(string[] args)<br />

{<br />

for(int i= 0; i


NOEA/IT <strong>–</strong> Programmeringsteknologi/<strong>C#</strong>.NET FEN/2004-02-20<br />

Vi vil prøve at lave en metode mere, som arbejder på sekvenser. Metoden skal tælle antal store<br />

tal i en sekvens:<br />

Vi giver den navnet countBigOnes. Metoden skal returnere et heltal - nemlig antallet af store tal -<br />

og have en sekvens som parameter. Vi vedtager, at i denne sammenhæng er et tal stort, hvis det<br />

er større end 20.<br />

En algoritme, som løser opgaven, kan udvikles udfra følgende idé: Kik på hvert element i<br />

sekvensen, hvis tallet er større end 20, så tæl en variabel op med én.<br />

Alle elementer skal undersøges, så der er tydeligvis tal om en sweep-algoritme. Elementerne skal<br />

ikke ændres, så vi kan bruge foreach-løkken i <strong>C#</strong>:<br />

Placeres denne metode i klassen TestSeqInt kan den kaldes fra Main() med:<br />

Console.WriteLine(CountBigOnes(sekvens);<br />

Andre abstrakte <strong>datatyper</strong><br />

public static int CountBigOnes(ArrayList s)<br />

{<br />

int antal= 0;<br />

foreach(int x in s)<br />

if(x>20) antal++;<br />

return antal;<br />

}<br />

I det følgende vil vi kort kikke på en række andre hyppigt anvendte abstrakte <strong>datatyper</strong>.<br />

Stak<br />

Stakken er en abstrakt datatype, som gemmer data efter LIFO (Last In First Out)-princippet. De<br />

almindelige operationer er:<br />

• Push(e), som placerer elementet e øverst på stakken<br />

• Top(), som returner det seneste placerede element fra stakken uden at ændre stakken<br />

• Pop(), som fjerner (og evt. returnerer) det seneste placerede element fra stakken.<br />

7/9


NOEA/IT <strong>–</strong> Programmeringsteknologi/<strong>C#</strong>.NET FEN/2004-02-20<br />

Endvidere vil stakken som regel have operationer, som kan oplyse, om den er tom, og hvor<br />

mange elementer den indeholder.<br />

Stakke implementeres ofte ved at anvende en sekvens eller en kædet liste.<br />

Kø<br />

End kø fungerer efter FIFO (First In Last Out)-princippet. Operationer er bl.a.:<br />

• Enqueue(e), som placerer elementet e sidst i køen<br />

• Front(), som returnerer det forreste element (det element, som har været i køen længst)<br />

uden at ændre køen<br />

• Dequeue(), som fjerner (og evt. returnerer) det forreste element (det element, som har<br />

været i køen længst)<br />

Som stakken har køen som regel også operationer, som kan oplyse, om den er tom, og hvor<br />

mange elementer den indeholder.<br />

Også køer implementeres ofte ved at anvende en sekvens eller en kædet liste.<br />

Dictionary<br />

Sekvenser, stakke og køer er eksempler på det, man kalder positionsbasere ADT’er, idet<br />

elementer lagres og hentes ud igen i en eller anden rækkefølge. Dicionary eller Map, som<br />

ADT’en også kaldes, er der imod værdibaseret, idet elementerne kendes ud fra deres værdi.<br />

Dictionary lagrer par af nøgler og værdier: (key, value). Fx kan nøglen være et telefonnummer og<br />

værdien et objekt med kontaktoplysninger (navn, adresse, email etc.).<br />

Almindelige operationer på et dictionary er:<br />

• Insert(key, value), indsætter et nyt element i dictionaryet (ofte med pre-betingelse, at key<br />

ikke findes i forvejen)<br />

• Contains(key), returnerer sand, hvis dictionaryet indeholder et element par med den<br />

angivne key. Ændrer ikke dictionaryet.<br />

• Retreive(key), som returner værdien svarende til den angivne key (ofte med prebetingelse,<br />

at key findes). Ændrer ikke dictionaryet.<br />

• Delete(key), sletter elementparret med den angivne key.<br />

Som stakken og køen har dictionary som regel også operationer, som kan oplyse, om den er tom,<br />

og hvor mange elementer den indeholder. Endvidere kan der være mulighed for at iterere<br />

gennem dictionaryet i nøgleorden.<br />

8/9


NOEA/IT <strong>–</strong> Programmeringsteknologi/<strong>C#</strong>.NET FEN/2004-02-20<br />

De fleste moderne programmeringssprog (også <strong>C#</strong>/.NET) tilbyder en række standardklasser og <strong>–</strong><br />

interfaces, som realiserer disse ADT’er. I .NET findes de i namespacet System.Collections og i<br />

.NET2 i en forbedret og udvidet <strong>version</strong> i namespacet System.Collections.Generics.<br />

Opgave<br />

Undersøg hvilke ADT’er, der tilbydes i System.Collections og/eller System.Collections.Generics.<br />

9/9

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!