



<html>
<head>
  <title>javabog.dk -  - Rekursion</title>
  <link rev="stylesheet" type="text/css" href="../typografi.css">
  <meta name="description" content="Lærebog i Java. Af Jacob Nordfalk. Udkommet hos Forlaget Globe">
  <meta name="keywords" content="designmønster, programmering, OOP, objekter, klasser, objektorienteret programmering, Java, JSP, lærebog, UML, IT">
</head>
<body bgcolor="#ffffff">



<a href='http://javabog.dk/'>javabog.dk</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href='kapitel2.jsp'>&lt;&lt; forrige</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href='indhold.jsp'>indhold</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href='kapitel4.jsp'>n&aelig;ste &gt;&gt;</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href='kode/'>programeksempler</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href='../index_VP.html'>om bogen</a>

<H1 CLASS="western" STYLE="">3 <a name='afsn3'></a>Rekursion</H1>
<DIV ID="Indholdsfortegnelse4">
  <P STYLE="margin-top: 0.3cm; margin-bottom: 0cm"><BR>
  </P>
  <P STYLE="margin-left: 0.3cm; margin-top: 0.15cm; margin-bottom: 0cm">
  <FONT FACE="Helvetica, sans-serif"><FONT SIZE=2 STYLE="font-size: 11pt"><B>3.1
  Introduktion til rekursive algoritmer  56</B></FONT></FONT></P>
  <P STYLE="margin-left: 0.6cm; margin-top: 0.08cm; margin-bottom: 0cm">
  <FONT FACE="Helvetica, sans-serif"><FONT SIZE=2 STYLE="font-size: 9pt">3.1.1
  Folde en rekursion ud  56</FONT></FONT></P>
  <P STYLE="margin-left: 0.6cm; margin-top: 0.08cm; margin-bottom: 0cm">
  <FONT FACE="Helvetica, sans-serif"><FONT SIZE=2 STYLE="font-size: 9pt">3.1.2
  Foruds&aelig;tninger for rekursion  56</FONT></FONT></P>
  <P STYLE="margin-left: 0.3cm; margin-top: 0.15cm; margin-bottom: 0cm">
  <FONT FACE="Helvetica, sans-serif"><FONT SIZE=2 STYLE="font-size: 11pt"><B>3.2
  Rekursiv listning af filer  57</B></FONT></FONT></P>
  <P STYLE="margin-left: 0.3cm; margin-top: 0.15cm; margin-bottom: 0cm">
  <FONT FACE="Helvetica, sans-serif"><FONT SIZE=2 STYLE="font-size: 11pt"><B>3.3
  Beregning af et matematisk udtryk  58</B></FONT></FONT></P>
  <P STYLE="margin-left: 0.3cm; margin-top: 0.15cm; margin-bottom: 0cm">
  <FONT FACE="Helvetica, sans-serif"><FONT SIZE=2 STYLE="font-size: 11pt"><B>3.4
  Tegning af fraktaler  60</B></FONT></FONT></P>
  <P STYLE="margin-left: 0.3cm; margin-top: 0.15cm; margin-bottom: 0cm">
  <FONT FACE="Helvetica, sans-serif"><FONT SIZE=2 STYLE="font-size: 11pt"><B>3.5
  Opgaver  61</B></FONT></FONT></P>
</DIV>

























<P CLASS="kapiteloversigt-western">Forst&aring;else af rekursion er
en foruds&aelig;tning for at forst&aring; et eksempel i <a href='kapitel4.jsp#afsn4.7.3'>afsnit 4.7.3</a>.
Derudover foruds&aelig;ttes kapitlet ikke i resten af bogen.</P>
<P CLASS="western" STYLE="">Rekursion er
velegnet, hvis en opgave kan deles op i mindre tilsvarende
delopgaver.</P>
<H2 CLASS="western">3.1 <a name='afsn3.1'></a>Introduktion til rekursive algoritmer</SPAN></H2>
<P CLASS="western">Hvis en metode kalder sig selv, er der tale om
rekursion. F.eks.:</P>
<PRE CLASS="kode-western">public class Rekursion
{
  public static void main(String[] arg)
  {
    <SPAN LANG="da-DK">t&aelig;lNed</SPAN>(3);
  }

  public static void <B>t&aelig;lNed(int t&aelig;ller)</B>
  {
    System.out.print(t&aelig;ller+&quot; &quot;);
    if (t&aelig;ller&gt;0) <B>t&aelig;lNed(t&aelig;ller-1)</B>; <I>// t&aelig;lNed() kalder sig selv !!</I>
  }
}</PRE>
<HR>
<PRE CLASS="kode-western">3 2 1 0</PRE><P CLASS="western">
Fidusen er, at t&aelig;ller-parameteren eksisterer &eacute;n gang for
hver gang, t&aelig;lNed() bliver kaldt. S&aring; n&aring;r t&aelig;lNed()
vender tilbage til kalderen, som ogs&aring; er t&aelig;lNed(), er
t&aelig;llers v&aelig;rdi bevaret som f&oslash;r kaldet.</P>
<H3 CLASS="western">3.1.1 <a name='afsn3.1.1'></a>Folde en rekursion ud</H3>
<P CLASS="western">Er man uvant med rekursion, kan det v&aelig;re
sv&aelig;rt at gennemskue, hvad der sker. Husk da, at et kald til en
metode er uafh&aelig;ngigt af, om metoden eventuelt allerede &quot;er
i gang med&quot; at blive kaldt. Ovenst&aring;ende rekursion kunne
&quot;foldes ud&quot; til f&oslash;lgende program:</P>
<PRE CLASS="kode-western">public class <SPAN LANG="da-DK">RekursionUdfoldet</SPAN>
{
  public static void main(String[] arg)
  {
    <B>t&aelig;lNed(3)</B>;
  }

  public static void <B>t&aelig;lNed</B>(int t&aelig;ller)
  {
    System.out.print(t&aelig;ller+&quot; &quot;);
    if (t&aelig;ller&gt;0) <B><SPAN LANG="da-DK">t&aelig;lNedA</SPAN></B>(t&aelig;ller-1);    <I>// kald t&aelig;lNedA(2)</I>
  }

  public static void <B>t&aelig;lNedA</B>(int t&aelig;ller)
  {
    System.out.print(t&aelig;ller+&quot; &quot;);
    if (t&aelig;ller&gt;0) <B><SPAN LANG="da-DK">t&aelig;lNedB</SPAN></B>(t&aelig;ller-1);    <I>// kald t&aelig;lNedB(1)</I>
  }
 
  public static void <B>t&aelig;lNedB</B>(int t&aelig;ller)
  {
    System.out.print(t&aelig;ller+&quot; &quot;);
    if (t&aelig;ller&gt;0) <B><SPAN LANG="da-DK">t&aelig;lNedC</SPAN></B>(t&aelig;ller-1);    <I>// kald t&aelig;lNedC(0)</I>
  }

  public static void <B>t&aelig;lNedC</B>(int t&aelig;ller)
  {
    System.out.print(t&aelig;ller+&quot; &quot;);
    if (t&aelig;ller&gt;0) t&aelig;lNedC(t&aelig;ller-1);    <I>// kalder ikke videre, da t&aelig;ller=0</I>
  }
}</PRE>
<HR>
<PRE CLASS="kode-western">3 2 1 0</PRE><P CLASS="western">
Det er klart, at rekursion nemt kan f&oslash;re til uendelige l&oslash;kker,
hvis man ikke passer p&aring;. 
</P>
<H3 CLASS="western">3.1.2 <a name='afsn3.1.2'></a>Foruds&aelig;tninger for rekursion</H3>
<P CLASS="western">Man kan groft sagt v&aelig;re sikker p&aring;, at
der ikke opst&aring;r en uendelig l&oslash;kke, hvis man kan p&aring;vise,
at alle videre kald sker med en <I>mindre</I> opgave end der blev
kaldt med, og at en tilstr&aelig;kkelig lille opgave bliver udf&oslash;rt
uden et videre kald. 
</P>
<P CLASS="western">Herover bliver opgaven mindre og mindre, fordi
t&aelig;ller bliver reduceret med 1 i hvert kald, og fordi t&aelig;lNed()
kun kalder sig selv, hvis t&aelig;ller er st&oslash;rre end 0.</P>
<BLOCKQUOTE CLASS="definition-western">Rekursion kan l&oslash;se en
slags opgave hvis:</BLOCKQUOTE>
<OL>
  <LI><BLOCKQUOTE CLASS="definition-western">Opgaven kan deles om i
  mindre bidder af samme karakter som den oprindelige opgave</BLOCKQUOTE>
  <LI><BLOCKQUOTE CLASS="definition-western">En tilstr&aelig;kkelig
  lille opgave altid kan l&oslash;ses</BLOCKQUOTE>
</OL>
<H2 CLASS="western">3.2 <a name='afsn3.2'></a>Rekursiv listning af filer</SPAN></H2>
<P CLASS="western">Her ses et andet eksempel p&aring; rekursion, hvor
filer i det aktuelle katalog og alle underkataloger listes rekursivt.</P>
<P CLASS="western">Klassen File, der repr&aelig;senterer en fil eller
et katalog, kan bruges til at navigere i filsystemet, slette eller
omd&oslash;be filer eller kataloger og afl&aelig;se eller s&aelig;tte
deres attributter.</P>
<P CLASS="western">Det f&oslash;lgende eksempel lister alle filerne i
det aktuelle katalog. Er der nogle underkataloger, listes indholdet
af dem ogs&aring; (<SPAN LANG="da-DK">rekursionen</SPAN> best&aring;r
i, at <SPAN LANG="da-DK">listKatalog</SPAN>() kalder sig selv).</P>
<PRE CLASS="kode-western">import <SPAN LANG="da-DK">java.io.</SPAN>*;
public class <SPAN LANG="da-DK">ListFilerRekursivt</SPAN>
{
  public static void main(String[] arg)
  {
    File kat = new File(&quot;.&quot;);   <I>// objekt der repr&aelig;senterer det aktuelle katalog</I>
    listKatalog(kat);
  }

  private static void listKatalog(File kat)
  {
    File[] filer = <SPAN LANG="da-DK">kat.listFiles</SPAN>();

    for (int i=0; i&lt;<SPAN LANG="da-DK">filer.length</SPAN>; i++) 
    {
      File f = filer[i];

      if (<SPAN LANG="da-DK">f.isDirectory</SPAN>())
      {
        System.out.println(&quot;Katalog &quot;+f+&quot;:&quot;);
        <B>listKatalog(f)</B>;                         <I>// kald listKatalog() rekursivt</I>
        System.out.println(&quot;Katalog &quot;+f+&quot; slut.&quot;);
      } else {
        System.out.println(f);                  <I>// udskriv filens navn og sti</I>
      }
    }
  }
}</PRE>
<HR>
<PRE CLASS="kode-western">./<SPAN LANG="da-DK">ListFilerRekursivt.class</SPAN>
./<SPAN LANG="da-DK">ListFilerRekursivt.java</SPAN>
Katalog ./Desktop:
./Desktop/<SPAN LANG="da-DK">Home.desktop</SPAN>
./Desktop/<SPAN LANG="da-DK">MandrakeClub.desktop</SPAN>
Katalog ./Desktop/Removable media:
./Desktop/Removable media/Floppy
./Desktop/Removable media/CD-ROM
Katalog ./Desktop/Removable media slut.
Katalog ./Desktop/Affald:
Katalog ./Desktop/Affald slut.
Katalog ./Desktop slut.
Katalog ./tmp:
Katalog ./tmp slut.</PRE><P CLASS="western">
Programmet er startet fra et katalog, der indeholdt
ListFilerRekursivt.java og ListFilerRekursivt.class og
underkatalogerne Desktop (der igen indeholdt bl.a. Home.desktop,
MandrakeClub.desktop og underkatalogerne Removable media og Affald)
og tmp.</P>
<H2 CLASS="western">3.3 <a name='afsn3.3'></a>Beregning af et matematisk udtryk</SPAN></H2>
<P CLASS="western">Det f&oslash;lgende program kan analysere en
streng og udregne et matematisk udtryk med de fire regnearter,
sinus-funktionen og et vilk&aring;rligt antal parenteser.</P>
<PRE CLASS="kode-western">public class <SPAN LANG="da-DK">Formelberegning</SPAN>
{
<I>  /**</I>
<I>   * Finder f&oslash;rste position af en operator,<SPAN LANG="da-DK"> f.eks. </SPAN>+, -, * eller /.</I>
<I>   * G&aring;r uden om de operatorer, der er inde i en parentes.</I>
<I>   *<SPAN LANG="da-DK"> Simpel </SPAN>l&oslash;sning, der ikke tager h&oslash;jde for parenteser: <SPAN LANG="da-DK">udtryk.indexOf</SPAN>(tegn)</I>
<I>   */</I>
  private static int <SPAN LANG="da-DK">findUdenforParenteser</SPAN>(char tegn, String udtryk)
  {
    int par = 0;
    for (int i = 0; i&lt;<SPAN LANG="da-DK">udtryk.length</SPAN>(); i++)
    {
      char t = <SPAN LANG="da-DK">udtryk.charAt</SPAN>(i);
      if (t == tegn &amp;&amp; par==0) return i;<I> // tegn fundet udenfor parenteser!</I>
      else if (t == '(') par++;          <I>// vi g&aring;r ind i en parentes</I>
      else if (t == ')') par--;          <I>// vi g&aring;r ud af en parentes</I>
    }
    return -1; <I>// tegnet blev ikke fundet (i hvert fald ikke udenfor parenteser)</I>
  }


<I>  /**</I>
<I>   * Beregner v&aelig;rdien at et udtryk.</I>
<I>   * @param udtryk En streng med udtrykket, der skal beregnes.</I>
<I>   * @return v&aelig;rdien af udtrykket.</I>
<I>   * @throws <SPAN LANG="da-DK">NumberFormatException</SPAN> hvis udtrykket ikke er gyldigt</I>
<I>   */</I>
  public static double <B>beregn(String udtryk)</B>
  {
    udtryk = <SPAN LANG="da-DK">udtryk.trim</SPAN>();                  <I>// fjern overfl&oslash;dige blanktegn</I>
    for (int <SPAN LANG="da-DK">opNr</SPAN> = 0; opNr &lt; 4; opNr++)     <I>// l&oslash;b gennem de fire regnearter</I>
    {
      char op = &quot;+-*/&quot;<SPAN LANG="da-DK">.charAt</SPAN>(opNr);         <I>// op er nu '+', '-', '*' eller '/'</I>
      int pos = findUdenforParenteser(op,udtryk);
      if (pos &gt; 0)                           <I>// findes op i udtrykket?</I>
      {
        String <B>vs = <SPAN LANG="da-DK">udtryk.substring</SPAN>(0,pos)</B>; <I>// ja, find venstresiden</I>
        String <B>hs = udtryk.substring(pos+1)</B>; <I>// find h&oslash;jresiden</I>

        <I>// metoden kalder nu sig selv og analyserer hvert element i strengen</I>
        double <B><SPAN LANG="da-DK">vsr</SPAN> = beregn(vs)</B>;             <I>// beregn h&oslash;jresidens v&aelig;rdi</I>
        System.out.println(&quot;beregn(&quot;+vs+&quot;) = &quot;+vsr);
        double <B><SPAN LANG="da-DK">hsr</SPAN> = beregn(hs)</B>;             <I>// beregn venstresidens v&aelig;rdi</I>
        System.out.println(&quot;beregn(&quot;+hs+&quot;) = &quot;+hsr);

        if (op == '+') <B>return vsr + hsr</B>;     <I>// beregn resultat og <SPAN LANG="da-DK">return&eacute;r</SPAN></I>
        if (op == '-') <B>return vsr - hsr</B>;
        if (op == '*') <B>return vsr * hsr</B>;
        <B>return vsr / hsr</B>;
      }
    }
<I>    // Hvis vi kommer herned kunne der<SPAN LANG="da-DK"> ikke </SPAN>dele op i flere operatorer</I>
    if (<SPAN LANG="da-DK">udtryk.startsWith</SPAN>(&quot;(&quot;) &amp;&amp; <SPAN LANG="da-DK">udtryk.endsWith</SPAN>(&quot;)&quot;))   <I>// parenteser omkring?</I>
    {
      udtryk = udtryk.substring(1,udtryk.length()-1);     <I>// fjern dem</I>
      return beregn(udtryk);                              <I>// beregn indmad</I>
    }
    if (udtryk.startsWith(&quot;sin(&quot;) &amp;&amp; udtryk.endsWith(&quot;)&quot;))<I>// sinus-funktion</I>
    {
      udtryk = udtryk.substring(4,udtryk.length()-1);     <I>// fjern 'sin(' og )</I>
      double resultat = beregn(udtryk);                   <I>// beregn parameteren</I>
      System.out.println(&quot;beregn(&quot;+udtryk+&quot;) = &quot;+resultat);
      return <SPAN LANG="da-DK">Math.sin</SPAN>(resultat);
    }
    <I>// intet andet fundet - s&aring; m&aring; det v&aelig;re et tal! </I>
<I>    // (ellers kastes NumberFormatException)</I>
    return <SPAN LANG="da-DK">Double.parseDouble</SPAN>(udtryk);
  }

  public static void main(String[] arg)
  {
    String <B>formel = &quot;(1+2)*3 - sin(4/5*(6-7))&quot;</B>;
    double v&aelig;rdi = <B>beregn(formel)</B>;
    System.out.println(&quot;Formlen &quot;+formel+&quot; er beregnet til &quot;+v&aelig;rdi);
  }
}</PRE><P CLASS="western">
Herunder ses udskriften fra programmet ved udregning af &quot;(1+2)*3
- sin(4/5*(6-7))&quot;:</P>
<PRE CLASS="kode-western">beregn(1) = 1.0
beregn(2) = 2.0
beregn((1+2)) = 3.0
beregn(3) = 3.0
beregn((1+2)*3 ) = 9.0
beregn(4) = 4.0
beregn(5) = 5.0
beregn(4/5) = 0.8
beregn(6) = 6.0
beregn(7) = 7.0
beregn((6-7)) = -1.0
beregn(4/5*(6-7)) = -0.8
beregn( sin(4/5*(6-7))) = -0.7173560908995228
Formlen (1+2)*3 - sin(4/5*(6-7)) er beregnet til 9.717356090899523</PRE><P CLASS="western">
Metoden beregn() deler strengen op i mindre bidder, som den udregner
v&aelig;rdien af ved at kalde sig selv rekursivt. For eksempel deles
&quot;(1+2)*3 - sin(4*5/(6-7))&quot; op i delene &quot;(1+2)*3&quot;
og &quot;sin(4*5/(6-7))&quot;, der hver is&aelig;r udregnes ved at
kalde beregn(). 
</P>
<P CLASS="western">Bliver beregn() kaldt med en streng, der ikke kan
opdeles yderligere, antages det, at strengen indeholder et tal, som
bliver fundet med et kald til Double.parseDouble().</P>
<P CLASS="western">R&aelig;kkef&oslash;lgen af kaldene i programmet
er:</P>
<UL>
  <LI><P CLASS="western" STYLE="margin-top: 0cm; margin-bottom: 0cm">beregn(&quot;(1+2)*3
  - sin(4*5/(6-7))&quot;), der kalder</P>
  <LI><P CLASS="western" STYLE="margin-top: 0cm; margin-bottom: 0cm">beregn(&quot;(1+2)*3&quot;),
  der kalder</P>
</UL>
<UL>
  <LI><P CLASS="western" STYLE="margin-top: 0cm; margin-bottom: 0cm">beregn(&quot;(1+2)&quot;),
  der kalder</P>
  <LI><P CLASS="western" STYLE="margin-top: 0cm; margin-bottom: 0cm">beregn(&quot;1+2&quot;),
  der kalder</P>
  <LI><P CLASS="western" STYLE="margin-top: 0cm; margin-bottom: 0cm">beregn(&quot;1&quot;),
  der giver 1</P>
  <LI><P CLASS="western" STYLE="margin-top: 0cm; margin-bottom: 0cm">beregn(&quot;2&quot;),
  der giver 2</P>
  <LI><P CLASS="western" STYLE="margin-top: 0cm; margin-bottom: 0cm">returv&aelig;rdierne
  1 og 2 l&aelig;gges sammen og giver 3</P>
  <LI><P CLASS="western" STYLE="margin-top: 0cm; margin-bottom: 0cm">beregn(&quot;3&quot;),
  der giver 3</P>
  <LI><P CLASS="western" STYLE="margin-top: 0cm; margin-bottom: 0cm">returv&aelig;rdierne
  3 og 3 multipliceres og giver 9</P>
</UL>
<UL>
  <LI><P CLASS="western" STYLE="margin-top: 0cm; margin-bottom: 0cm">beregn(&quot;sin(4/5*(6-7))&quot;),
  der kalder</P>
  <LI><P CLASS="western" STYLE="margin-top: 0cm; margin-bottom: 0cm">beregn(&quot;4/5*(6-7)&quot;),
  der kalder</P>
  <LI><P CLASS="western" STYLE="margin-top: 0cm; margin-bottom: 0cm">beregn(&quot;4/5&quot;),
  der kalder</P>
  <LI><P CLASS="western" STYLE="margin-top: 0cm; margin-bottom: 0cm">beregn(&quot;4&quot;),
  der giver 4</P>
  <LI><P CLASS="western" STYLE="margin-top: 0cm; margin-bottom: 0cm">beregn(&quot;5&quot;),
  der giver 5</P>
  <LI><P CLASS="western" STYLE="margin-top: 0cm; margin-bottom: 0cm">returv&aelig;rdierne
  4 og 5 ganges sammen og giver 0.8</P>
  <LI><P CLASS="western" STYLE="margin-top: 0cm; margin-bottom: 0cm">beregn(&quot;(6-7)&quot;),
  der kalder</P>
  <LI><P CLASS="western" STYLE="margin-top: 0cm; margin-bottom: 0cm">beregn(&quot;6-7&quot;),
  der kalder</P>
  <LI><P CLASS="western" STYLE="margin-top: 0cm; margin-bottom: 0cm">beregn(&quot;6&quot;),
  der giver 6</P>
  <LI><P CLASS="western" STYLE="margin-top: 0cm; margin-bottom: 0cm">beregn(&quot;7&quot;),
  der giver 7</P>
  <LI><P CLASS="western" STYLE="margin-top: 0cm; margin-bottom: 0cm">returv&aelig;rdierne
  4 og 5 tr&aelig;kkes fra hinanden og giver -1</P>
  <LI><P CLASS="western" STYLE="margin-top: 0cm; margin-bottom: 0cm">returv&aelig;rdierne
  0.8 og -1 divideres med hinanden og giver -0.8</P>
  <LI><P CLASS="western" STYLE="margin-top: 0cm; margin-bottom: 0cm">sinus
  til returv&aelig;rdien -0.8 beregnes og giver -0.717</P>
  <LI><P CLASS="western" STYLE="margin-top: 0cm; margin-bottom: 0cm">returv&aelig;rdierne
  9 og -0.717 tr&aelig;kkes fra hinanden og giver 9.717</P>
</UL>
<P CLASS="western">Indrykningerne illustrerer dybden af rekursionen
(hvor mange gange beregn() er i gang med at kalde sig selv).</P>
<P CLASS="western">Vi vil bygge videre p&aring; ovenst&aring;ende
eksempel i <a href='kapitel4.jsp#afsn4.7.3'>afsnit 4.7.3</a>.</P>
<H2 CLASS="western" STYLE="">3.4 <a name='afsn3.4'></a>Tegning af
fraktaler</SPAN></H2>
<P CLASS="western">Dette eksempel tegner et <SPAN LANG="da-DK">fraktalt</SPAN>
tr&aelig;. En <SPAN LANG="da-DK">fraktal</SPAN> er en struktur, hvor
man, hvis man g&aring;r t&aelig;t p&aring; en del af strukturen,
opdager, at delen har lige s&aring; mange detaljer som helheden. 
</P>
<P CLASS="western">Her er rekursion velegnet, da man blot kan lave en
metode tegnGren(), der tegner en gren i et bestemt st&oslash;rrelsesforhold
ved at tegne &quot;stammen&quot; i grenen og derefter tegne mindre
grene (med kald til tegnGren() med mindre st&oslash;rrelsesforhold).</P>
<PRE CLASS="kode-western">import <SPAN LANG="da-DK">java.awt.</SPAN>*;
public class <SPAN LANG="da-DK">Fraktaltrae</SPAN> extends Frame
{
<I>  /**</I>
<I>   * Tegner et fraktalt tr&aelig;. Hver gren er i sig selv et tr&aelig;.</I>
<I>   * @param x   x-koordinaten hvor tr&aelig;ets rod skal tegnes</I>
<I>   * @param y   y-koordinaten hvor tr&aelig;ets rod skal tegnes</I>
<I>   * @param dx  x-forskydning fra rod til tr&aelig;ets f&oslash;rste forgrening</I>
<I>   * @param dy  y-forskydning fra rod til tr&aelig;ets f&oslash;rste forgrening</I>
<I>   * @param <SPAN LANG="da-DK">str</SPAN> tr&aelig;ets st&oslash;rrelse</I>
<I>   * @param g   Graphics-objektet</I>
<I>   */</I>
<I><B>  public void tegnGren(Graphics g, int x, int y, int dx, int dy, int str)</B></I>
  {
    if (str &lt; 1) return;<I> // vi vil ikke tegne forsvindende sm&aring; grene</I>
    
    <SPAN LANG="da-DK">g.drawLine</SPAN>(x, y, x+dx, y+dy);                 <I>// tegn stammen</I>

    <B>tegnGren(g, x+dx, y+dy,-str/2, str/2, str/2)</B>; <I>// tegn gren til venstre</I>
    <B>tegnGren(g, x+dx, y+dy, str/10,str/5, str/3)</B>; <I>// lille gren lidt til h&oslash;jre</I>
    <B>tegnGren(g, x+dx, y+dy, str/2, str/2, str/2)</B>; <I>// tegn gren til h&oslash;jre</I>
  }

  public void paint(Graphics g)
  {
    tegnGren(g,410,30,0,0,400);
  }

  public static void main(String[] arg)
  {
    Fraktaltrae tr&aelig; = new Fraktaltrae();
    <SPAN LANG="da-DK">tr&aelig;.setSize</SPAN>(850, 450);
    <SPAN LANG="da-DK">tr&aelig;.setVisible</SPAN>(true);
  }
}</PRE><P CLASS="western">
P&aring; figuren kan man se, hvordan hver gren er en formindsket
udgave af hele tr&aelig;et.</P>
<P CLASS="western" ALIGN=CENTER><IMG SRC="bog4_html_m2cf62095.png" NAME="Graphic10" ALIGN=BOTTOM BORDER=0></P>
<H2 CLASS="western">3.5 <a name='afsn3.5'></a>Opgaver</SPAN></H2>
<OL>
  <LI><P CLASS="western">Pr&oslash;v eksemplerne <SPAN LANG="da-DK">Rekursion</SPAN>,
  ListFilerRekursivt, Formelberegning og Fraktaltrae.</P>
  <LI><P CLASS="western">Hvad skriver det f&oslash;lgende program ud?
  Regn det ud uden at k&oslash;re programmet. <BR>Pr&oslash;v derefter
  at k&oslash;re det, og f&oslash;lg med i variablernes v&aelig;rdier.</P>
</OL>
<PRE CLASS="kode-western">public class Rekursionsopgave
{
  public static String <SPAN LANG="da-DK">kaldRekursivt</SPAN>(String s)
  {
    if (<SPAN LANG="da-DK">s.length</SPAN>()&lt;=1) return s;

    String f&oslash;rsteTegn = <SPAN LANG="da-DK">s.substring</SPAN>(0,1);
    String resten     = s.substring(1);
    String resten2    = kaldRekursivt( resten );
    String <SPAN LANG="da-DK">detHele</SPAN>    = resten2 + f&oslash;rsteTegn;
    return detHele;
  }

  public static void main(String[] arg)
  {
    String resultat = kaldRekursivt(&quot;Hej verden!&quot;);
    System.out.println(resultat);
  }
}</PRE>


<a href='http://javabog.dk/'>javabog.dk</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href='kapitel2.jsp'>&lt;&lt; forrige</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href='indhold.jsp'>indhold</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href='kapitel4.jsp'>n&aelig;ste &gt;&gt;</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href='kode/'>programeksempler</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href='../index_VP.html'>om bogen</a>
<hr>
<font size=-2>http://javabog.dk/ - <b></b> af Jacob Nordfalk.
<br>
  Licens og kopiering under <a href='http://www.linuxbog.dk/licens.html'>&Aring;ben Dokumentlicens</a> (&Aring;DL)
  hvor intet andet er nævnt (71% af værket).
</font>
<br>
Ønsker du at se de sidste 29% af dette værk (362838 tegn)
skal du købe bogen. Så får du pæne figurer og layout, stikordsregister og en trykt bog med i købet.
<!-- netlæser: Wget/1.10, autoHent: true  -->
     

</body>
</html>
