Board index » delphi » Stack overflow at binary tree balance

Stack overflow at binary tree balance

Hi,

i am doing my homework. I have to write a program using a balanced tree.
It is required to balance the tree.
So i wrote a function to do so.
On calling the function i get an stack overflow.

Any help ?
Thanks a lot.

My code:

program binaerbaum;
uses crt;
type name= string[12];
     pointer= ^baum;
     baum= record
       vorname: name;
       nachname: name;
       rechts: pointer;
       links: pointer;
     end;

var zeiger: pointer;
    antwort: char;
    vorname: name;
    nachname: name;
    zaehler, d: integer;
    pfad: string;

{--------------------------------------------------------------------------}

procedure einfuegen(var baumpointer:pointer; vorneu, nachneu: name);
begin
  if baumpointer= nil then
  begin
    new(baumpointer);
    baumpointer^.nachname:= nachneu;
    baumpointer^.vorname:= vorneu;
    baumpointer^.links:= nil;
    baumpointer^.rechts:= nil;
  end
  else
    if nachneu<baumpointer^.nachname then
      einfuegen(baumpointer^.links, nachneu, vorneu)
    else
      einfuegen(baumpointer^.rechts, nachneu, vorneu);
end;
{--------------------------------------------------------------------------}

procedure eingabe (var vn, nn: name);
begin
  clrscr;
  write('Vorname: ');
  readln(vn);
  write('Nachname: ', vorname,', ');
  readln(nn);
end;
{--------------------------------------------------------------------------}

procedure ausgabe(bpointer:pointer; var zaehler: integer; pfad: string);
begin
  if bpointer <> nil then
    begin
      if bpointer^.links<> nil then
        ausgabe(bpointer^.links, zaehler, pfad + 'L');

      zaehler:= zaehler + 1;
      write( zaehler:3,'  ', bpointer^.nachname,', ', bpointer^.vorname);
      gotoXY(50, whereY); writeln(pfad+'*');

      if bpointer^.rechts<> nil then
        ausgabe(bpointer^.rechts, zaehler, pfad + 'R');

     end;
end;
{--------------------------------------------------------------------------}

procedure liste;
var antw: char;
begin
  repeat
  eingabe (vorname, nachname);
  einfuegen(zeiger, nachname, vorname);
  writeln('weiteren namen');
  readln(antw);
  until antw= 'n';
  readln;
end;
{--------------------------------------------------------------------------}
procedure loeschen(var bp: pointer; vn, nn: name);
var rettel: pointer;
    retter: pointer;
begin
  if (nn < bp^.nachname) and (bp<> nil) then
    loeschen(bp^.links, nn, vn)
  else
    if (nn > bp^.nachname) and (bp<> nil) then
      loeschen(bp^.rechts, nn, vn)
    else
      if (nn= bp^.nachname) and (vn= bp^.vorname) then
        begin
          retter:= bp^.rechts;
          rettel:= bp^.links;
          dispose(bp);
          bp:= retter;
          while retter^.links <> nil do
           retter:= retter^.links;
           retter^.links:= rettel;
        end
        else
          writeln('name nicht vorhanden');
end;
{--------------------------------------------------------------------------}

function count(baum: pointer): integer;
begin
  if baum = nil then
    count:= 0
  else
    count:= count(baum^.rechts) + count(baum^.links);
end;
{--------------------------------------------------------------------------}

procedure optimieren(var baum: pointer );
var p: pointer;
begin
  while count(baum^.links)> count(baum^.rechts) do
  begin
    p := baum^.links;
    baum^.links:= p^.rechts;
    p^.rechts:= baum;
    baum:= p;
  end;
  while count(baum^.links) < count(baum^.rechts) do
  begin
    p:= baum^.rechts;
    baum^.rechts:= p^.links;
    p^.links:= baum;
    baum:= p;
  end;
  optimieren(baum^.links);
end;
{--------------------------------------------------------------------------}

begin
  clrscr;
  new(zeiger);
  zeiger:= nil;
  d:=0;
  repeat
  writeln;
  writeln('W"hlen sie ihren Men punkt aus');
  writeln('0.- Programende');
  writeln('1.- neue Liste erstellen');
  writeln('2.- Element in Baum einf gen');
  writeln('3.- Element aus Baum l"schen');
  writeln('4.- Baum optimieren');
  writeln('5.- Baum in Datei speichern');
  writeln('6.- Datei "ffnen');
  readln(antwort);
  case antwort of '1': begin
                         liste;
                         zaehler:= 0;
                         ausgabe(zeiger, zaehler, pfad);
                         writeln;
                         writeln(zaehler,'. Namen sind vorhanden');
                         writeln('max Pfadl"nge: ', zaehler-1);
                         writeln('optimale Pfadl"nge: ',
                                trunc(ln(zaehler)/ln(2)));
                       end;
                  '2': begin
                         eingabe(vorname, nachname);
                         einfuegen(zeiger, nachname, vorname);
                         zaehler:= 0;
                         ausgabe(zeiger, zaehler, pfad);
                         writeln;
                         writeln(zaehler,'. Namen sind vorhanden');
                         writeln('max Pfadl"nge:', zaehler-1);
                         writeln('optimale Pfadl"nge: ',
                                trunc(ln(zaehler)/ln(2)));
                       end;
                  '3': begin
                         if zeiger= nil then exit;
                         eingabe(vorname, nachname);
                         loeschen(zeiger, nachname, vorname);
                         zaehler:= 0;
                         ausgabe(zeiger, zaehler, pfad);
                         writeln;
                         writeln(zaehler,'. Namen sind vorhanden');
                         writeln('max Pfadl"nge:', zaehler-1);
                         writeln('optimale Pfadl"nge: ',
                                trunc(ln(zaehler)/ln(2)));
                       end;
                  '4': begin
                         if zeiger<> nil then
                         optimieren(zeiger);
                       end;
                  '5': begin
                       end;
                  '6': begin
                       end;
  end;
  until antwort= '0';
end.

 

Re:Stack overflow at binary tree balance


Antje Ruff schrieb:

Hallo Antje!

Quote
> Hi,

> i am doing my homework. I have to write a program using a balanced tree.
> It is required to balance the tree.
> So i wrote a function to do so.
> On calling the function i get an stack overflow.

Although recognizing that you're writing in my mother language I answer
in english for the other readers here who don't speak german well
enough... ;-)

You do know what a stack-overflow is/means?

You may enlarge the stack by using the {$M } directive at the beginning
of the program. Another thing is: optimieren (what most likely causes
the overflow) is programmed recursively, thus needing much stack space
if you have enough data. On every call to optimieren the lokally
declared pointer and other things (returnadress = Rcksprungadresse so
that the program knows where it has to continue after the procedure has
finished etc.) are put on the stack. If possible try to change the
algorithm here to some which doesn't use recursion. Maybe you can use
some loops which go over the data. This will save much memory on the
stack, no matter how large your tree structure becomes.

Quote

> Any help ?
> Thanks a lot.

Greetings

Markus (BA-Student WI 5. Semester)

Re:Stack overflow at binary tree balance


Quote
Markus Humm wrote:
> You may enlarge the stack by using the {$M } directive at the
> beginning of the program.

That is almost always the wrong solution.

Quote
> Another thing is: optimieren (what most
> likely causes the overflow) is programmed recursively, thus needing
> much stack space if you have enough data.

Well, after digging through the posted code I think the problem is as
follows:

optimieren does not check for a termination condition (like NIL for both
links and rechts). So regardless of what it does, it *always* calls
itself.

Quote
> Markus (BA-Student WI 5. Semester)

Seems I have to revise my prejudices about WI-students. ;-)

Vinzent.

--
I have yet to see any problem, however complicated, which, when looked
at in the right way, did not become still more complicated.
                -- Poul Anderson

Re:Stack overflow at binary tree balance


hi antje

just a short look at your code ...

{-----------------------------------------------------------------------
---}

Quote

> function count(baum: pointer): integer;
> begin
>   if baum = nil then
>     count:= 0
>   else
>     count:= count(baum^.rechts) + count(baum^.links);

!     count:= 1 + count(baum^.rechts) + count(baum^.links);

Quote
> end;

{-----------------------------------------------------------------------
---}

gruss
jo

Re:Stack overflow at binary tree balance


Quote
Antje Ruff wrote:

> Hi,

> i am doing my homework. I have to write a program using a balanced tree.
> It is required to balance the tree.
> So i wrote a function to do so.
> On calling the function i get an stack overflow.

Just one more advice:

Quote
> program binaerbaum;
> uses crt;
> type name= string[12];
>      pointer= ^baum;

Uh oh! Don't do this.

Pointer is a built-in type and should (almost?) NEVER be redifined! A
pointer is an untyped type that can point to anything. You are
redefining pointer to a typed pointer to baum. Please choose a better
name for that, for example 'PBaum' or 'baumpointer'.

This has nothing to do with your problem but I hope you will change that
anyway.

Wolf

(btw, there is de.comp.lang.pascal)

Re:Stack overflow at binary tree balance


Vinzent Hoefler schrieb:

Quote
> Markus Humm wrote:

>>You may enlarge the stack by using the {$M } directive at the
>>beginning of the program.

> That is almost always the wrong solution.

I only suggested this one for the possibility that ALL other things
failed...to find the real cause of the trouble is ALWAYS better (but not
always more time efficient)

Quote

>>Another thing is: optimieren (what most
>>likely causes the overflow) is programmed recursively, thus needing
>>much stack space if you have enough data.

> Well, after digging through the posted code I think the problem is as
> follows:

> optimieren does not check for a termination condition (like NIL for both
> links and rechts). So regardless of what it does, it *always* calls
> itself.

Yes, you're right. I didn't look too deep in the code so i missed this
fact. I only saw the recursion and then stopped looking due to some
shortage of time just now.

Quote

>>Markus (BA-Student WI 5. Semester)

> Seems I have to revise my prejudices about WI-students. ;-)

Hm, I do hope that you come now to the conclusion that they simply don't
have enough time to study other people's problems well enough to solve
them completely. This is due to the fact that they do have so much
lessons, exams and other study related things (projects)...students of
other subjects DO have MUCH MORE free time just now! They do specialize
on some topics which doesn't compensate the fact that the WI-Students do
still have the whole load (depth and range) of subjects.

Greetins

Markus

PS: I've got to stop now, because I've got to learn for a little test
tomorrow...

Re:Stack overflow at binary tree balance


Quote
Markus Humm wrote:
> Vinzent Hoefler schrieb:
>> Markus Humm wrote:

>> Well, after digging through the posted code I think the problem is as
>> follows:

>> optimieren does not check for a termination condition (like NIL for
>> both links and rechts). So regardless of what it does, it *always*
>> calls itself.

> Yes, you're right. I didn't look too deep in the code so i missed this
> fact.

To be honest, I just looked at it, because you mentioned this routine...

Quote
>>>Markus (BA-Student WI 5. Semester)

>> Seems I have to revise my prejudices about WI-students. ;-)

> Hm, I do hope that you come now to the conclusion that they simply
> don't have enough time to study other people's problems well enough to
> solve them completely.

I meant it the other way around. I'm positively surprised that you are
studying WI. I would not have expect it. Doesn't have to do much with
this posting alone.

Quote
> PS: I've got to stop now, because I've got to learn for a little test
> tomorrow...

Good luck.

Vinzent.

--
YOW!!  Everybody out of the GENETIC POOL!"

Re:Stack overflow at binary tree balance


"Wolf Behrenhoff" <NoSpamPleaseButThisIsVa...@gmx.net> schreef in
bericht news:3E1D9EE6.D38DF0E3@gmx.net...

Quote
> Antje Ruff wrote:

> > Hi,

> > i am doing my homework. I have to write a program using a balanced
tree.
> > It is required to balance the tree.
> > So i wrote a function to do so.
> > On calling the function i get an stack overflow.

> Just one more advice:

> > program binaerbaum;
> > uses crt;
> > type name= string[12];
> >      pointer= ^baum;

> Uh oh! Don't do this.

> Pointer is a built-in type and should (almost?) NEVER be redifined! A
> pointer is an untyped type that can point to anything. You are
> redefining pointer to a typed pointer to baum. Please choose a better
> name for that, for example 'PBaum' or 'baumpointer'.

> This has nothing to do with your problem but I hope you will change
that
> anyway.

On the other hand, in the past when the numeric coprocessor was not
common and TP was not able to emulate it, I used this as a programming
trick.

By putting in a commonly called unit

type real=single;
or
real=double;

all the 6 byte reals in my programs were replaced with 4 or 8 byte ones
that could be handled by the coprocessor.
This coprocessor real handling turned out to be faster by a factor 20 or
so.

--
Femme

Re:Stack overflow at binary tree balance


Quote
Femme Verbeek wrote:

> "Wolf Behrenhoff" <NoSpamPleaseButThisIsVa...@gmx.net> schreef in
> bericht news:3E1D9EE6.D38DF0E3@gmx.net...
> > Just one more advice:

> > > program binaerbaum;
> > > uses crt;
> > > type name= string[12];
> > >      pointer= ^baum;

> > Uh oh! Don't do this.

> > Pointer is a built-in type and should (almost?) NEVER be redifined! A
> > pointer is an untyped type that can point to anything. You are
> > redefining pointer to a typed pointer to baum. Please choose a better
> > name for that, for example 'PBaum' or 'baumpointer'.

> > This has nothing to do with your problem but I hope you will change that
> > anyway.

> On the other hand, in the past when the numeric coprocessor was not
> common and TP was not able to emulate it, I used this as a programming
> trick.

> By putting in a commonly called unit

> type real=single;
> or
> real=double;

> all the 6 byte reals in my programs were replaced with 4 or 8 byte ones
> that could be handled by the coprocessor.
> This coprocessor real handling turned out to be faster by a factor 20 or
> so.

That is something different. That is why I wrote _almost_ never. There
might be some situations where redefining a type makes sense. Because
real isn't compatibe to anything and IMHO therefore a useless type, it
makes sense to redefine real as double. Also redefining SearchRec makes
sense when writing a unit which supports LFNs.

But nevertheless pointer=^baum should not be used in this case.

As a rule of thumb never redefine a bulit-in type unless you exactly
know what you are doing (and why).

Wolf

Re:Stack overflow at binary tree balance


Quote
"Femme Verbeek" <fv[at]{*word*104}jet[dot]nl> wrote in message

news:v1s14i19e6hc3c@corp.supernews.com...

Quote
> By putting in a commonly called unit

> type real=single;
> or
> real=double;

> all the 6 byte reals in my programs were replaced with 4 or 8 byte ones
> that could be handled by the coprocessor.
> This coprocessor real handling turned out to be faster by a factor 20 or
> so.

The following, if placed in a commonly used unit will do the job
automatically:

type
  { Real type [re]defininition }
{$ifopt N+}
  Real = Double;
{$else}
{$ifopt E+}
  Real = Double;
{$endif E+}
{$endif N+}

A Compile|Build is needed of all units if either the $N or $E compiler
option is changed.
--
Jay

Jason Burgon. Author of Graphic Vision
Version 2.21 available from:
http://homepage.ntlworld.com/gvision

Re:Stack overflow at binary tree balance


"Jason Birgon" <gvision.nos...@ntlworld.com> schreef in bericht
news:4zrT9.2609$tx.143944@newsfep1-gui.server.ntli.net...

Quote
> "Femme Verbeek" <fv[at]{*word*104}jet[dot]nl> wrote in message
> news:v1s14i19e6hc3c@corp.supernews.com...

> > By putting in a commonly called unit

> > type real=single;
> > or
> > real=double;

> > all the 6 byte reals in my programs were replaced with 4 or 8 byte
ones
> > that could be handled by the coprocessor.
> > This coprocessor real handling turned out to be faster by a factor
20 or
> > so.

> The following, if placed in a commonly used unit will do the job
> automatically:

> type
>   { Real type [re]defininition }
> {$ifopt N+}
>   Real = Double;
> {$else}
> {$ifopt E+}
>   Real = Double;
> {$endif E+}
> {$endif N+}

> A Compile|Build is needed of all units if either the $N or $E compiler
> option is changed.

I like the idea, however, since the $E option was created, somewhere in
TP version 4 or so,  this is not necessary any more.
You can replace this code simply by
{$N+}
{$E+}
type real=double;

The reason is that this way the running code will automatically look for
the presence of a coprocessor.
If found, it will use corpocessor instructions,
else it will use emulation.
The emulated Double floating point handling turned out to be faster than
the original 6 byte real handling. Therefore you should always check
both!!!!!

If you N unchecked, you will get an error upon first use of any of the
real types other than 6 byte real itself, regardless of the status of
the E option.

Perhaps this should be mentioned in the FAQ.  Timo?

--
Femme

Re:Stack overflow at binary tree balance


Hello!

I don't waht to interrupt your reasonalbe discussion here, but I just
wanted to remark that you're getting slightly OT here. Why not just
start a new thread like Type redefinition & Coprocessor... or similar?

Greetings

Markus

Re:Stack overflow at binary tree balance


[snip]

Quote

> I meant it the other way around. I'm positively surprised that you are
> studying WI. I would not have expect it. Doesn't have to do much with
> this posting alone.

Why this? WI is a practical subject and the BA system does enhance this
further...

Quote

>>PS: I've got to stop now, because I've got to learn for a little test
>>tomorrow...

> Good luck.

Thanks. It was only ADA. 50% of the points needed and that should be the
cause. A good mark would be fine, but we'll see...

Markus

Re:Stack overflow at binary tree balance


JRS:  In article <v1tspm13lb2...@corp.supernews.com>, seen in
news:comp.lang.pascal.borland, Femme Verbeek <fv@[at]> posted at Fri, 10
Jan 2003 17:22:14 :-

Quote

>The emulated Double floating point handling turned out to be faster than
>the original 6 byte real handling. Therefore you should always check
>both!!!!!

Not always.

I had a program that needed to do floating-point both in the main
routine and in a hardware interrupt service routine.

For this to be successful using only IEEE types, one must not only save
the state of the FPU, which can be done; but one must also deal with the
non re-entrant helper routines for FPU operations, which I did not
manage.

Instead, I used exclusively the IEEE types in the main program and the
pure-software 6-byte types in the ISR (or vice versa) - this was
successful.  It was a BP7 program; DPMI, I think, not Windows; it would
actually run in a Windows 3.x DOS box.

See <URL:http://www.merlyn.demon.co.uk/pas-real.htm#FloatISR>.

--
? John Stockton, Surrey, UK.  j...@merlyn.demon.co.uk   Turnpike v4.00   MIME. ?
  <URL:http://www.merlyn.demon.co.uk/> TP/BP/Delphi/&c., FAQqy topics & links;
  <URL:http://www.merlyn.demon.co.uk/clpb-faq.txt> Pedt Scragg: c.l.p.b. mFAQ;
  <URL:ftp://garbo.uwasa.fi/pc/link/tsfaqp.zip> Timo Salmi's Turbo Pascal FAQ.

Re:Stack overflow at binary tree balance


Quote
"Femme Verbeek" <fv[at]{*word*104}jet[dot]nl> wrote in message

news:v1tspm13lb20b8@corp.supernews.com...

Quote

> "Jason Birgon" <gvision.nos...@ntlworld.com> schreef in bericht
> > type
> >   { Real type [re]defininition }
> > {$ifopt N+}
> >   Real = Double;
> > {$else}
> > {$ifopt E+}
> >   Real = Double;
> > {$endif E+}
> > {$endif N+}

> > A Compile|Build is needed of all units if either the $N or $E compiler
> > option is changed.

> I like the idea, however, since the $E option was created, somewhere in
> TP version 4 or so,  this is not necessary any more.
> You can replace this code simply by
> {$N+}
> {$E+}
> type real=double;

As Dr Stockton points out in his response; not always. I'm currently working
on a concrete manufacturing control system that uses the "RTKernel" Pascal
library by OnTime Informatik. This provides a multi-threaded environment
that would suffer a considerable increase in context-switching time if the
co-processor were used. This is because the state of the co-pro would have
to be saved and restored on almost every context-switch of this particular
application.

--
Jay

Jason Burgon. Author of Graphic Vision
Version 2.21 available from:
http://homepage.ntlworld.com/gvision

Other Threads