Abstrakte datatyper – C#-version
Abstrakte datatyper – C#-version
Abstrakte datatyper – C#-version
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