Article View: comp.lang.modula2
Article #787Wirth B-Tree Source
From: cs200cap cs200cap
Date: Fri, 08 Jun 1990 01:57
Date: Fri, 08 Jun 1990 01:57
288 lines
13338 bytes
13338 bytes
From: cs200cap@st1.vuw.ac.nz
Date: 2 Jun 90 05:01:43 GMT
Organization: Victoria University of Wellington
Message-ID: <1697.26669f77@st1.vuw.ac.nz>
Newsgroups: comp.lang.modula2
In article, vixie@decwrl.dec.com (Paul A Vixie) writes:
> There are some B-tree routines in Wirth's "Algorythms and Data Structures"
> (second version, source code in M2 rather than P). I converted them to C
> and posted them to comp.sources.unix a few years back, but the originals
> are still in the book :-)..
Yeah, I adapted Wirth's B-Tree routines from the 2nd edition. His original
ones are reprinted below without permission (it helps if you buy/borrow a
copy of his book so you can follow what is going on as his variable names
are a little cryptic).
The Tab character size should be 4, so you will need to replace the tab
characters with 4 spaces below.
Create a file of integers, if an integer is -ve, then the code below will
try and delete the integer from the tree. If the integer is +ve then
the code will insert the integer in the tree, if it's already in the tree
then it will INC(record.count).
pat -- cs200cap@st1.vuw.ac.nz
MODULE BTree;
(* B-tree procedures by Niklaus Wirth *)
FROM InOut IMPORT OpenInput, OpenOutput, CloseInput, CloseOutput, ReadInt,
Done, WriteInt, WriteString, WriteLn, Write;
FROM Storage IMPORT ALLOCATE;
CONST n=9; (* Order of b-tree *)
TYPE PPtr=POINTER TO Page;
Item= RECORD
key : INTEGER;
p : PPtr;
count : CARDINAL;
END;
Page= RECORD
m : [0..2*n]; (* no. of items on page *)
p0 : PPtr;
e : ARRAY[1..2*n] OF Item;
END;
VAR root,q : PPtr;
x : INTEGER;
h : BOOLEAN;
u : Item;
PROCEDURE search(x : INTEGER; a : PPtr; VAR h : BOOLEAN; VAR v :Item);
(* Search key x in B-tree with root a; if found, increment counter.
Otherwise insert new item with key x. If an item is passed up,
assign it to v. h = "tree has become higher" *)
VAR i, L, R : CARDINAL;
b : PPtr;
u : Item;
BEGIN (* ~h *)
IF a=NIL
THEN
h:=TRUE; (* not in tree *)
WITH v DO
key:=x;
count:=1;
p:=NIL;
END; (* of WITH *)
ELSE
WITH a^ DO
L:=1;
R:=m+1; (* binary search *)
WHILE L<R DO
i:=(L+R) DIV 2;
IF e[i].key<=x
THEN
L:=i+1;
ELSE
R:=i;
END; (* of IF *)
END; (* of WHILE *)
R:=R-1;
IF (R>0) & (e[R].key=x)
THEN
INC(e[R].count)
ELSE (* item not on this page *)
IF R=0
THEN
search(x,p0,h,u);
ELSE
search(x,e[R].p,h,u)
END; (* IF *)
IF h
THEN (* insert u to the right of e[R] *)
IF m<2*n
THEN
h:=FALSE;
m:=m+1;
FOR i:=m TO R+2 BY -1 DO
e[i]:=e[i-1] END;
e[R+1]:=u
ELSE ALLOCATE(b, SIZE(Page)); (* overflow *)
(* split a into a,b and assign the middle item to v *)
IF R<=n
THEN
IF R=n
THEN
v:=u
ELSE
v:=e[n];
FOR i:=n TO R+2 BY -1 DO e[i]:=e[i-1] END;
e[R+1]:=u
END;
FOR i:=1 TO n DO b^.e[i]:=a^.e[i+n] END
ELSE (* insert in riMODULE BTree;
(* B-tree procedures by Niklaus Wirth *)
FROM InOut IMPORT OpenInpu b^.e[i]:=a^.e[i+n+1]
END; (* of FOR *)
b^.e[R]:=u;
FOR i:=R+1 TO n DO
b^.e[i]:=a^.e[i+n]
END; (* of for *)
END; (* of IF *)
m:=n;
b^.m:=n;
b^.p0:=v.p;
v.p:=b;
END;
END;
END;
END;
END;
END search;
PROCEDURE underflow(c, a:PPtr; s:CARDINAL; VAR h: BOOLEAN);
(* a=underflowing page, c=ancestor page,
s=index of deleted item in c, h:= *)
VAR b:PPtr;
VAR i,k,mb,mc: CARDINAL;
BEGIN
mc:=c^.m; (* h, a^.m=n-1 *)
IF s<mc
THEN
(* b:=page to the right of a *)
s:=s+1;
b:=c^.e[s].p;
mb:=b^.m;
k:=(mb-n+1) DIV 2;
(* k=no. of items available on page b *)
a^.e[n]:=c^.e[s];
a^.e[n].p:=b^.p0;
IF k>0
THEN
(* move k items from b to a *)
FOR i:=1 TO k-1 DO
a^.e[i+n]:=b^.e[i]
END;
c^.e[s]:=b^.e[k];
c^.e[s].p:=b;
b^.p0:=b^.e[k].p;
mb:=mb-k;
FOR i:=1 TO mb DO
b^.e[i]:=b^.e[i+k]
END;
b^.m:=mb;
a^.m:=n-1+k;
h:=FALSE
ELSE (* merge pages a and b *)
FOR i:=1 TO n DO
a^.e[i+n]:=b^.e[i]
END;
FOR i:=s TO mc-1 DO
c^.e[i]:=c^.e[i+1]
END;
a^.m:=2*n;
c^.m:=mc-1;
h:=mc<=n;
(* Deallocate(b) *)
END;
ELSE (* b:= page to the left of a *)
IF s=1
THEN
b:=c^.p0
ELSE
b:=c^.e[s-1].p
END;
mb:=b^.m+1;
k:=(mb-n) DIV 2;
IF k>0
THEN
(* move k items for page b to a *)
FOR i:=n-1 TO 1 BY -1 DO
a^.e[i+k]:=a^.e[i]
END;
a^.e[k]:=c^.e[s];
a^.e[k].p:=a^.p0;
mb:=mb-k;
FOR i:=k-1 TO 1 BY -1 DO
a^.e[i]:=b^.e[i+mb]
END;
a^.p0:=b^.e[mb].p;
c^.e[s]:=b^.e[mb];
c^.e[s].p:=a;
b^.m:=mb-1;
a^.m:=n-1+k;
h:=FALSE
ELSE
(* merge pages a and b *)
b^.e[mb]:=c^.e[s];
b^.e[mb].p:=a^.p0;
FOR i:=1 TO n-1 DO
b^.e[i+mb]:=a^.e[i]
END;
b^.m:=2*n;
c^.m:=mc-1;
h:=mc<=n;
(* Deallocate(a) *)
END
END
END underflow;
PROCEDU b^.e[i]:=a^.e[i+n+1]
END; (* of FOR *)
b^.e[R]:=u;
FOR i: a; if a page underflow arises,
balance with adjacent page or merge; h:= "page a is undersize" *)
VAR i,L,R: CARDINAL;
q : PPtr;
PROCEDURE del(P:PPtr; VAR h:BOOLEAN);
VAR q:PPtr; (* global a,R *)
BEGIN
WITH P^ DO
q:=e[m].p;
IF q # NIL
THEN
del(q,h);
IF h
THEN
underflow(P,q,m,h)
END
ELSE
P^.e[m].p:=a^.e[R].p;
a^.e[R]:=P^.e[m];
m:=m-1;
h:=m<n
END
END
END del;
BEGIN
IF a=NIL
THEN (* x not in tree *)
h:=FALSE;
ELSE
WITH a^ DO
L:=1;
R:=m+1; (* binary search *)
WHILE L<R DO
i:=(L+R) DIV 2;
IF e[i].key<x
THEN
L:=i+1;
ELSE
R:=i
END (* of IF *)
END; (* of WHILE *)
--
uucp: uunet!m2xenix!puddle!42.0!cs200cap@st1.vuw.ac.nz
Internet: cs200cap@st1.vuw.ac.nz@p0.f42.n105.z1.fidonet.org
Technical Details
Message-ID:
<5378.26731962@puddle.fidonet.org>Path:
arc1-ca.pugleaf.net!utzoo!utgpu!news-server.csri.toronto.edu!mailrus!tut.cis.ohio-state.edu!zaphod.mps.ohio-state.edu!usc!snorkelwacker!mintaka!ogicse!zephyr.ens.tek.com!tektronix!nosun!qiclab!m2xenix!puddle!st1.vuw.ac.nz@p0.f42.n105.z1.fidonet.org!cs200cap@st1.vuw.ac.nzShow Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!utgpu!news-server.csri.toronto.edu!mailrus!tut.cis.ohio-state.edu!zaphod.mps.ohio-state.edu!usc!snorkelwacker!mintaka!ogicse!zephyr.ens.tek.com!tektronix!nosun!qiclab!m2xenix!puddle!st1.vuw.ac.nz@p0.f42.n105.z1.fidonet.org!cs200cap@st1.vuw.ac.nz From: cs200cap@st1.vuw.ac.nz@p0.f42.n105.z1.fidonet.org (cs200cap@st1.vuw.ac.nz) Newsgroups: comp.lang.modula2 Subject: Wirth B-Tree Source Message-ID: <5378.26731962@puddle.fidonet.org> Date: 8 Jun 90 01:57:00 GMT Sender: ufgate@puddle.fidonet.org (newsout1.26) Organization: FidoNet node 1:105/42.0 - Bink of an Aye, Portland OR Lines: 288