Try this:


unit genericset (t);
interface
type genset=pointer;

(*! The functions getnext, getlast and getfirst must never be called on an
empty set. The function
getnext should never be called on the last element of a set. *)
procedure genericsetnext(var v:t;s:genset);
procedure genericsetfirst(var v:t;s:genset);
procedure genericsetlast(var v:t;s:genset);
function genericsetislast(v:t;s:genset):boolean;
function isemptygenericset(s:genset):boolean;
function genericsetnotempty(s:genset):boolean;
procedure addtogenericset(var s:genset;v:t);
function genericsetsingleton(singleton:t):genset;
function genericsetunion(s1,s2:genset):genset;
function genericsetdifference(s1,s2:genset):genset;
function genericsetintersection(s1,s2:genset):genset;
function genericsetsymetricdifference(s1,s2:genset):genset;
function genericseteq(s1,s2:genset):boolean;
function genericsetneq(s1,s2:genset):boolean;
function isin(s:genset;v:t):boolean;
procedure genericsetisin(s:genset;v:t;var b:boolean);
procedure emptygenericset(var newset:genset);{ set newset to be empty }
function genericsetle(s1,s2:genset):boolean;{ s1<=s2}
function genericsetge(s1,s2:genset):boolean;
implementation
type pset=^setrec;
     setrec = record
                value:t;
                left,
                right:pset;
                bal:integer;
                end;
        cheat = record
                case boolean of
                true:(yes:pset;);
                false:(no:pointer);
                end;
                procedure phex(p:pointer);
        var r:record
                case boolean of
                true:(i:integer);
                false:(p:pointer);
                end;
        begin
                r.p:=p;
                write(r.i);
        end;
        function pointer2pset(p:pointer):pset;

        begin
                   pointer2pset:=p;
        end;

        function newnode(var key:t; l,r:pset):pset;
        var temp:pset;
        begin

                new(temp);
                with temp^ do begin
                        value:=key; left:=l; right:=r;
                end;
                newnode:=temp;
        end;
        procedure genericsetisin(s:genset;v:t;var b:boolean);
        begin b:=isin(s,v);end;
        function genericsetlt(s1,s2:genset):boolean;
                begin genericsetlt:= not 
isemptygenericset(genericsetdifference(s2,s1))
end;
        function genericsetgt(s1,s2:genset):boolean;
                begin genericsetgt:=genericsetlt(s2,s1); end;
        function genericsetle(s1,s2:genset):boolean;
                begin genericsetle:= not genericsetgt(s1,s2); end;
        function genericsetge(s1,s2:genset):boolean;
                begin genericsetge:=genericsetle(s2,s1) end;
        function genericsetneq(s1,s2:genset):boolean;
                begin genericsetneq:= not genericseteq(s1,s2); end;
        function genericseteq(s1,s2:genset):boolean;
                begin   
genericseteq:=isemptygenericset(genericsetsymetricdifference(s1,s2))
end;

        function genericsetsymetricdifference(s1,s2:genset):genset;
        begin
        
genericsetsymetricdifference:=genericsetdifference(genericsetunion(s1,s2),genericsetintersection(s1,s2));
        end;
        function genericsetintersection(s1,s2:genset):genset;
        var temp:genset;
                procedure rec(p:pset);
                begin
                        if p<>nil then
                        with p^ do begin
                                if isin(s2,value) then 
addtogenericset(temp,value);
                                rec(right);rec(left);
                        end
                end;
        begin
                emptygenericset(temp);
                rec(pointer2pset(s1 ));
                genericsetintersection:=temp;
        end;
        function genericsetunion(s1,s2:genset):genset;
        var temp:genset;
                procedure rec(p:pset);
                begin
                        if p<>nil then
                        with p^ do begin
                                addtogenericset(temp,value);
                                rec(right);rec(left);
                        end
                end;
        begin
                {emptygenericset(temp);
                rec(pointer2pset(s1 ));}
                temp:=s1;
                rec(pointer2pset(s2 ));
                genericsetunion:=temp;
        end;
        function genericsetnotempty(s:genset):boolean;begin 
genericsetnotempty:=not
isemptygenericset(s) end;
        function isemptygenericset(s:genset):boolean;begin 
isemptygenericset:=s=nil
end;
        procedure emptygenericset(var newset:genset);
        begin 
                newset :=nil;
        end;
        function newset(v:t;l,r:pset):pset;
        var temp:pset;
        begin
                new(temp);
                with temp^ do
                begin
                   value:=v;left:=l;right:=nil;bal:=0;
                end;
                newset:=temp
        end;
        function find(p:pset;v:t):pset;
        begin

                if p=nil then find:=nil
                else with p^ do
                begin
                {   writeln('find ',v,' key ', p^.value);}
                   if v<value then find:=find(left,v)
                   else if value &lt; v then find:=find(right,v)
                        else find:=p;
                end;
        end;
        function del(var p:pset;v:t):pset;
        var dup,copy:pset;
        begin

                if p=nil then  del:=nil else begin
                  new (dup); dup^:=p^; copy:=p; p:=dup;
                  with p^ do
                  begin
                 
                   if v&lt;value then del:=del(left,v)
                   else if value &lt; v then del:=del(right,v)
                        else begin
                                del:=left;
                                p:=right;
                        end;
                  end;
                end;
        end;
        function isin(s:genset;v:t):boolean;begin 
              {  writeln('isin ', v);}
                isin:=find(pointer2pset(s ),v)&lt;>nil;
         end;
        procedure genericsetlast(var v:t;p1:genset);
                procedure genericsetright(p:pset);
                begin
                        with p^ do
                        begin
                                if right=nil then v:=value
                                else genericsetright(right)
                        end
                end;
        begin
                genericsetright(pointer2pset(p1 ));
                
        end;
        function genericsetislast(v:t;p1:genset):boolean;
        var v2:t;
        begin
                genericsetlast(v2,p1);
                
                genericsetislast:=v2=v;
        end;
        procedure genericsetfirst(var v:t;p1:genset);
                procedure genericsetleft(p:pset);
                begin
                        with p^ do
                        begin
                                if left=nil then v:=value
                                else genericsetleft(left)
                        end
                end;
        begin
                genericsetleft(pointer2pset(p1 ));
                
        end;
    function genericsetnextnode(p:pset;v:t):pset;
          var p1:pset;
          begin
                if p=nil then genericsetnextnode:=nil else
                with p^ do
                begin
                  if v<value then begin
                        p1:=genericsetnextnode(left,v);
                        if p1=nil then genericsetnextnode:=p else 
genericsetnextnode:=p1
                  end
                  else genericsetnextnode:=genericsetnextnode(right,v);
                end
          end;
        procedure genericsetnext(var v:t;s:genset);
        (*! Note that the genset s should never be nil when this is called. *)
          
          var p2:pset;
        begin
                p2:=genericsetnextnode(pointer2pset(s ),v);
                v:=p2^.value;
        end;

        type tree=pset;
        typekey=t;
        procedure lrot( var tp : tree );
        var     temp : tree;
                a : integer;
        begin
                temp := tp;
                tp:= tp^.right;
                temp^.right := tp^.left;
                tp^.left := temp;
                {*** adjust balance ***}
                a := temp^.bal;
                temp^.bal := a - 1 - ( tp^.bal max  0 );
                tp^.bal := ( a-2)min( a+tp^.bal-2)min( tp^.bal-1);
        end;
        procedure rrot( var tp : tree );
        var     temp : tree;
                b : integer;
        begin
                temp := tp;
                tp := tp^.left;
                temp^.left := tp^.right;
                tp^.right := temp;
                {*** adjust balance ***}
                b := temp^.bal;
                temp^.bal := b + 1 + ( -tp^.bal max 0 );
                tp^.bal := -(( -b-2)min( -b-tp^.bal-2)min( -tp^.bal-1));
        end;

        function insert( key : typekey; var tp : tree ) : integer;
        var     incr : integer;dup:tree;
        begin

                insert := 0;
                if tp = nil then begin
                        tp:= NewNode( key, nil, nil );
                        tp^.bal := 0;
                        insert := 1;
                end
                else if tp^.value = key then begin
                         {*** Key already in table ***}
                        
                end
                else begin
                   // make sure it is applicative and does not
                   // alter the original tree
                   new(dup);
                   dup^:=tp^;
                   tp:=dup;
                   with tp^ do
                   begin
                        if value&lt; key then
                                 incr := insert( key, right )
                else   
                                 incr := -insert( key, left );
                        bal := bal + incr;
                        
                        if (incr &lt;> 0) and (bal <> 0) then
                                if bal < -1 then
                                begin
                                
                        {*** left subtree too tall: right rotation needed
***}
                                        if left^.bal < 0 then   rrot( tp )
                                        else    begin   lrot( left ); rrot( tp )
end
                                end
                                else    if bal > 1 then
                                begin
                        {*** right subtree too tall: left rotation needed
***}
                                        if right^.bal > 0 then  lrot( tp )
                                        else    begin   rrot( right ); lrot( tp 
)
end
                                end
                        else    insert := 1;
                   end;
                end
        end;
        procedure addtogenericset(var s:genset; v:t);
        var p:pset;count:integer;
        begin
                if not isin(s,v) then begin
                        p:=pointer2pset(S );
                        count:=insert(v,p);
                        s :=p;  
                end;
        end;
        procedure removefromgenericset(var s:genset; v:t);
        var p,p2:pset;g:genset;
        begin
                if  isin(s,v) then begin
                        p:=pointer2pset(S );
                        p2:=del(p,v);
                        g:=p2;
                        s :=p;
                        s:=genericsetunion(s,g);        
                end;
        end;
        function genericsetsingleton(singleton :t):genset;
        var s:genset;
        begin
                emptygenericset(s);
                addtogenericset(s,singleton);
                genericsetsingleton:= s;
        end;
        function genericsetdifference(s1,s2:genset):genset;
        const threshold=2;
        var temp:genset;
                procedure rec(p:pset);
                begin
                        if p<>nil then
                        with p^ do begin
                                if not isin(s2,value) then 
addtogenericset(temp,value);
                                rec(right);rec(left);
                        end
                end;
                procedure recb(p:pset);
                begin
                        if p<>nil then
                        with p^ do begin
                                removefromgenericset(temp,value);
                                recb(right);recb(left);
                        end
                end;
                (*! this traverses the set just far enough to detemine if a set 
is bigger
than
                    a threshold size *)
                function big(p:pset;i:integer):integer;
                var j:integer;
                begin
                        if i>threshold then big:=i else
                        begin
                                if p=nil then big := i
                                else
                                begin
                                        j:= big(p^.left,i+1) ;
                                        if j>threshold then big:=j
                                        else big:=big(p^.right,j);
                                end
                        end;
                end;
        begin
                if big(pointer2pset(s2),0)>threshold then begin
                        emptygenericset(temp);
                        rec(pointer2pset(s1 ));
                end
                else begin
                        temp:=s1;
                        recb(pointer2pset(s2));
                end;
                genericsetdifference:=temp;
        end;


BEGIN
end.




--
Sent from: http://free-pascal-general.1045716.n5.nabble.com/
_______________________________________________
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Reply via email to