Routezoeker

advertisement
Reader en Writer
Object
leest en schrijft
bytes
decorator
store
Stream
leest
string en char
schrijft
string en char
TextReader
TextWriter
FileStream
StreamReader
StreamWriter
MemoryStream
StringReader
StringWriter
NetworkStream
BufferedStream
GZipStream
CryptoStream
BinaryReader
XmlReader
leest
XML-teksten
BinaryWriter
XmlWriter
leest
int en double
Methoden van Stream
abstract class FileStream
Stream
int Read (byte[] doel, int max)
{
{ for (int t=0; t<max; t++)
{ int b = this.ReadByte();
Stream
if (b==–1) return t;
FileStream
doel[t] = (byte) b ;
}
MemoryStream
return max;
}
NetworkStream
abstract
virtual int ReadByte ( ) ;
}
class FileStream : Stream
{
override int ReadByte ( )
{ return ............... }
}
Abstracte methode/klasse
 Abstracte methode:
methode zonder body
Stream
FileStream
MemoryStream
NetworkStream
Brush
SolidBrush
HatchBrush
 Abstracte klasse:
bevat abstracte methode
● kun je geen new
object van maken
● alleen bedoeld als
superklasse
Implementaties van
Collections
IEnumerable
ICollection
LinkedList
Queue
genummerd
zonder dubbele
Stack
IList
List
ISet
HashSet
SortedSet
IEnumerator
IComparator
IDictionary
SortedList
Sorted
Dictionary
Hoe doorloop je een IEnumerable ?
List
for (int t=0; t<alles.Count; t++)
doeIetsMet( alles[t] );
Collection
foreach (String s in alles)
doeIetsMet( s );
opdracht
for
(
foreach
expr
;
(
expr
type naam
;
in
expr
)
opdracht
expr
)
opdracht
Commandline programma
$> date
parameters
Wed Nov 2, 15:45
voor het programma
$> ls
aap.txt
hallo.doc
prog.cs
$> grep void prog.cs
prog.cs, line 6: void Main()
prog.cs, line 10: void teken()
$> ls
$>
> files.txt
output redirection
Grep: main
class Grep
{
static void Main ( string [ ] params )
{ if (params.Length==0)
System.out.println(“Usage: Grep pat file ...”);
else
for (int t=1; t<params.Length; t++)
Grep.bewerk( params[0], params[t] );
}
Grep: bewerk
static void bewerk (String pat, String naam)
{ TextReader reader; String regel;
try {
if (naam=="")
reader = Console.In;
else reader = new StreamReader (naam);
while
for
(int( n=1; (regel=reader.ReadLine() ) != null ; n++ )
if ( regel . IndexOf(pat) >= 0 )
Console.WriteLine( naam + n + regel );
} catch (Exception e) { Console.WriteLine(naam + e); }
Hoofdstuk 11.3
Algoritmen:
Zoeken in een
netwerk
Routeplanner
Spoorwegkaart:
Klik startpunt
Klik eindpunt
eind
start
Programma
bepaalt route
Klik nieuw
startpunt...
start
Modellering
elk traject heeft “kosten”;
route met laagste totaalprijs
is de beste
Zoek de “beste” route
Opbouw van het netwerk
staat in een file, met:
voor elke stad: naam en coördinaten
voor elke weg: 2 steden, en de kosten
stad Amersfoort
330 350
stad Amsterdam
250 310
stad Apeldoorn
420 330
weg Amersfoort Apeldoorn
weg Amsterdam Hilversum
weg Hilversum Amersfoort
43
29
16
Specificatie
 Bij eerste muisklik: en 3e, 5e, 7e...
aangewezen stad is het beginpunt
toon die in blauw
 Bij tweede muisklik: en 4e, 6e, 8e...
aangewezen stad is eindpunt
bereken de route, en toon die in rood
 Bij klik buiten een stad:
telt niet mee
Opdeling in klassen
Interactieve interface met EventHandler voor:
class RouteZoeker : Form
teken
klik
Belangrijke object-typen
class
class
class
class
Stad
Weg
Pad
Netwerk
met in elke klasse:
een constructor-methode
een methode Teken
om zichzelf te tekenen
...
Klasse-ontwerp
wat is ...
membervariabelen
wat kan ...
een object
methodeheaders
en hoe ?
methodebodies
De klasse RouteZoeker
class RouterZoeker : Form
{
Netwerk netwerk;
de “blauwe” stad
Stad stad1;
of null
Pad pad;
Button b;
TextBox t;
Label lab;
“het” netwerk
het “rode” pad
of null
we tekenen
alles zelf!
Event-handlers
void klik(..., MouseEventArgs mea) { ...... }
void teken(..., PaintEventArgs pea) { ...... }
De klasse Netwerk
class Netwerk
{
Stad [ ] Steden;
alle steden
op de kaart
ICollection<Stad> Steden;
ICollection<Weg> Wegen;
we gaan per stad
alle uitgaande
wegen bewaren
De klasse Stad
class Stad
{
string Naam;
Point Plek;
ICollection<Weg> Wegen;
Utrecht
De klasse Weg
class Weg
{
Stad Doel;
int Kosten;
De klasse Pad
class Pad
{
IList<Stad> Steden;
Stad Hier;
Pad Rest;
int Kosten;
ongeveer een
LinkedList,
maar dan
zelfgemaakt
null
Methoden van Stad
class Stad
{
String Naam;
Point Plek;
ICollection<Weg> wegen; static Font font = new ...
Stad ( String s, Point p )
{
Naam = s; Plek = p;
Wegen = new LinkedList<Weg> ( );
}
void Teken (Graphics gr, Brush br)
{
gr . FillRectangle(br
Utrecht
, Plek.X-5, Plek.Y-5, 10, 10 );
gr . DrawString (Naam, font, br
, Plek + new Size(6,-15) );
}
Methoden van Weg
class Weg
{
Stad Doel; int Kosten;
Weg ( Stad s, int k )
{
Doel =s; Kosten = k;
}
wordt niet
getekend
void Teken (Graphics gr, Pen pen ) , Stad bron )
{
gr . DrawLine ( pen, bron.Plek, Doel.Plek );
}
Methoden van Pad
class Pad
{ Stad Hier; Pad Rest; int Kosten;
totale kosten
van het pad
Pad ( Stad s, Pad r, int k )
{
Hier = s; Rest = r; Kosten = k;
if (Rest != null) Kosten += Rest.Kosten;
}
void Teken (Graphics gr, Brush br, Pen pen)
Hier . Teken (gr, br);
{
if (Rest != null)
{ gr.DrawLine( pen, Hier.Plek, Rest.Hier.Plek );
Rest . Teken (gr, br, pen);
}
}
Methoden van Netwerk
class Netwerk
{
ICollection<Stad> Steden;
Netwerk ( )
{
Steden = new LinkedList<Stad> ( );
}
void Teken (Graphics gr)
{
foreach ( Stad stad in Steden )
{
stad . Teken (gr, Brushes.Black);
foreach ( Weg w in stad.wegen )
w.Teken (gr, Pens.Black, stad)
}
}
bron
Methoden van RouteZoeker
class RouteZoeker
{
Netwerk netwerk; Stad stad1; Pad pad;
RouteZoeker ( )
{
netwerk = new Netwerk(); stad1=null; pad=null;
}
void teken (object o, PaintEventArgs pea)
{ Graphics gr = pea.Graphics;
netwerk . Teken (gr);
if (pad != null)
pad . Teken(gr, Brushes.Red, Pens.Red);
if (stad1 != null) stad1 . Teken(gr, Brushes.Blue);
}
Opbouw van het Netwerk
Lees een file met regels zoals:
commando
stad Almelo
520 280
stad Amersfoort
330 350
stad Amsterdam
250 310
stad Apeldoorn
420 330
stad Arnhem
410 380
weg Arnhem
Zutphen
weg Zutphen
Deventer
weg Deventer Zwolle
weg Amsterdam Weesp
weg Weesp
Hilversum
weg Hilversum Amersfoort
locatie
29
16
31
14
15
16
kosten
Opbouw van het Netwerk
void Lees (string filenaam )
StreamReader sr = new StreamReader(filenaam);
{
while ( (regel=sr.ReadLine()) != null )
{
string [] r = regel.Split(" ", StringSplitOptions.RemoveEmpty );
if (r.Length==4)
if (r[0] == "stad")
{
this . bouwStad (r[1]
new Point( int.Parse(r[2])
, int.Parse(r[3]) ) );
}
else
{ this.bouwWeg( r[1], r[2], int.Parse(r[3]) );
}
}
}
Opbouw van het Netwerk
void bouwStad (string naam, Point p)
{
Stad st = new Stad(naam, p);
Steden . Add (st);
Netwerk’s
}
void bouwWeg (string van, string naar, int kosten)
{ Stad st1 = this . vindStad (van);
Stad st2 = this . vindStad (naar);
}
st1 . BouwWeg (st2, kosten); class Stad {
st2 . BouwWeg (st1, kosten); void BouwWeg(Stad doel, int k)
{ Wegen . Add (
Stad’s
}
new Weg(doel, k) );
Opbouw van het Netwerk
Stad vindStad (String naam)
{
}
foreach ( Stad st in Steden )
{
if ( st.naam == naam )
return st ;
}
return null ;
Stad VindStad (Point p)
{
foreach ( Stad st in steden )
{
Math.Abs( p.X-st.Plek.X )< 5
if (
&& Math.Abs( p.Y-st.Plek.Y ) <5 )
return st ;
}
return null ;
Interactie in RouteZoeker
class RouteZoeker : Form
{
Netwerk netwerk;
Stad stad1;
Pad pad;
void klik (..., MouseEventArgs mea)
{
Stad s = netwerk . VindStad( mea.Location );
if ( s != null )
eerste klik { if (stad1==null) stad1 = s;
of
else { pad = netwerk . ZoekPad (stad1, s );
tweede klik?
stad1 = null;
}
this . Invalidate ();
}
}
Het zoek-algoritme
maak een stapel van
nog-niet-complete,
maar veelbelovende
paden
Pad ZoekPad
(Stad begin, Stad eind)
{
Stack<Pad> paden
= new Stack<Pad>();
Het zoeken begint...
Pad pad;
pad = new Pad(begin, null, 0);
null
paden . push (pad);
hij is niet
groot...
null
0
maar wel
veelbelovend!
Onderzoek paden uit stapel...
while ( paden.Count > 0 )
{
Pad pad = paden . pop();
if (pad.Hier==eind)
return pad;
foreach ( Weg weg in pad . Hier . Wegen )
{
beter = new Pad( weg.Doel, pad, weg.Kosten);
paden . Push(beter);
}
}
return null;
Pas op:
niet in een
kringetje zoeken!
één van de
wegen kom je
net vandaan!
foreach ( Weg weg in pad.Hier.Wegen )
{
if ( ! pad . Bevat (weg.Doel) )
{
beter = new Pad( weg.Doel, pad, weg.Kosten);
paden . Push(beter);
}
}
Niet de eerste oplossing,
maar de beste zoeken!
while ( ... )
{ pad = ...
if (compleet)
return pad;
for (...)
if ( !kring )
paden.Push(...)
}
return null;
beste = null;
while ( ... )
{ pad = ...
if (compleet)
if (beter)
beste=pad;
beste=pad;
return
pad;
for (...)
if ( !kring )&& !zinloos)
paden.Push(...)
}
return
return null;
beste;
Uitwerking
Wat is “beter” ?
if ( beste==null
|| pad.Kosten < beste.Kosten
) beste = pad;
Wat is “niet zinloos” ?
if ( beste==null
|| pad.Kosten + weg.Kosten < beste.Kosten
) paden.Push (new Pad (...) );
Verbetering van het algoritme
De meest veelbelovende
eerst onderzoeken
ordenen qua
afstand tot doel
Dus in volgorde van
afstand tot naar pushen
moet een
lComparer zijn
wegen = new SortedSet<Weg>( pad.Hier.Wegen , naar );
class Stad : IComparer<Weg> {
{ int Compare( Weg a, Weg b)
{ return this.afstand(b.doel) – this.afstand(a.doel);
}
Routezoeker compleet!
Download