home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / AVLTREE.ZIP / AVL.P
Encoding:
Text File  |  1988-02-29  |  64.1 KB  |  1,469 lines

  1. program AVL(input, output);
  2.  
  3. { --                                                                          }
  4. { -- Author      : Joubert Berger                                             }
  5. { -- Title       : Insert & Delete AVL routines                               }
  6. { -- Name        : avl.p                                                      }
  7. { --                                                                          }
  8. { -- Date        : May 27, 1988                                               }
  9. { --                                                                          }
  10. { -- Description :                                                            }
  11. { --               This program implements two AVL-routines, INSERT and       }
  12. { --               DELETE, and stores some and Social Security Numbers        }
  13. { --               it a tree.  It reads a one line command which contains the }
  14. { --               the action to be performed and the data that is used to    }
  15. { --               perform the action.  The actions allowed are:              }
  16. { --                                                                          }
  17. { --                    (A)dd    - Add the data to the tree                   }
  18. { --                    (D)elete - Delete the data from the tree              }
  19. { --                    (P)rint  - Print the tree                             }
  20. { --                    (C)lear  - Start a new tree, trash previous tree      }
  21. { --                    (S)top   - Stop the running of the program            }
  22. { --                                                                          }
  23. { --               After reading in the command it reads in the name which    }
  24. { --               may not be longer than 15 characters and must always be    }
  25. { --               paded with spaces if less than 15 character.  The Social   }
  26. { --               Security Number must be no longer than 9 characters long   }
  27. { --               and must also be paded with spaces if less than 9.  You    }
  28. { --               use either the "Name" or "SSN" filed as the key depending  }
  29. { --               on what you set the "KeyOnName" constant.  If set to TRUE  }
  30. { --               it will key on the name, else it will key on the Social    }
  31. { --               Security Number.  The "DEBUG" constant is used to print    }
  32. { --               information on what is being done to the tree to keep it   }
  33. { --               balanced.  If set to TRUE it will print what rotations     }
  34. { --               (i.e. left, right, double) it is doing to the tree.        }
  35. { --                                                                          }
  36. { --               NOTE: This was written on a VAX Workstation.  This         }
  37. { --                     implementation allows procedures to be passed        }
  38. { --                     to procedures.  This is not the case of Turbo        }
  39. { --                     Pascal Version 3.                                    }
  40. { --                                                                          }
  41.     
  42. const
  43.  
  44.    DEBUG         = true;                       { -- Is debug output printed   }
  45.    KeyOnName     = true;                       { -- Key on NAME or            }
  46.                                                {      SOCIAL SECURITY NUMBER  }
  47.  
  48.    NameLen       = 15;                         { -- Max. length of Name       }
  49.    SSNLen        = 9;                          { -- Max. length of SSN number }
  50.  
  51.    Offset        = 10;                         { -- Offset number of spaces   }
  52.                                                {      when printing tree      }
  53.  
  54. type
  55.  
  56.    BalanceType   = -1..+1;                     { -- Balance indicators:       }  
  57.                                                {  -1  -- Left subtree taller  }
  58.                                                {   0  -- Two subtrees equal   }
  59.                                                {  +1  -- Right subtree taller }   
  60.  
  61.    NamType       = array[1..NameLen] of char;  { -- Name goes in this type    }
  62.    SSNType       = array[1..SSNLen] of char;   { -- SSN # goes in this type   }
  63.  
  64.    TreePointer   = ^TreeType;                  { -- Pointer to tree node      }
  65.  
  66.    TreeType      = record
  67.                      Name      : NamType;      { -- Holds the name            }
  68.                      SSN       : SSNType;      { -- Holds the SSN number      }
  69.                      Left      : TreePointer;  { -- Left pointer              }
  70.                      Right     : TreePointer;  { -- Right pointer             }
  71.                      Condition : BalanceType   { -- Balance indicator         }
  72.                    end;  { record }
  73.  
  74.    StackPtr      = ^StackNodeType;             { -- Pointer to stack node     }
  75.    
  76.    StackNodeType = record
  77.                       Ptr     : TreePointer;   { -- Holds a tree pointer      }
  78.                       Next    : StackPtr       { -- Next pointer              }
  79.                    end;
  80.  
  81.    Stack         = StackPtr;                   { -- Pointer to stack node     }
  82.  
  83.  
  84. var
  85.  
  86.    Tree          : TreePointer;                { -- Tree pointer              }
  87.    NewRec        : TreeType   ;                { -- Holds new data read in    }
  88.    Comm          : char       ;                { -- Holds comm. to performed  }
  89.    Increase      : integer    ;                { -- Used to indicate if tree  }
  90.                                                {      changed hight           }
  91.  
  92.  
  93. {-----------------------------------------------------------------------------}
  94. {                                                                             }
  95. {             M I S C E L L A N E O U S     R O U T I N E S                   }
  96. {                                                                             }
  97. {-----------------------------------------------------------------------------}
  98.  
  99.  
  100. procedure BuildRecord(var Comm : char;
  101.                       var Rec  : TreeType);
  102.  
  103. {========================================}
  104. {                                        }
  105. {  This procedure reads in one line from }
  106. {  the input device and picks out the    }
  107. {  Command, Name, and Social Security    }
  108. {  Number.  If the name or SSN number is }
  109. {  less than the maximum length allowed  }
  110. {  it must be padded with spaces to fill }
  111. {  it up to its max.  It puts the name   }
  112. {  and SSN number in the "Rec" record    }
  113. {  and puts the command to be performed  }
  114. {  on the record in "Comm".              }
  115. {  The Command line must look as         }
  116. {  follows:                              }
  117. {    Command - starts at position 1      }
  118. {    Name    - starts at position 3      }
  119. {    SSN     - starts at position 19     }
  120. {                                        }
  121. {========================================}
  122.  
  123. var
  124.    Index : integer;                      { -- Used as a counter               }
  125.    ch    : char   ;                      { -- Character that is read in       }
  126.  
  127. begin
  128.    Rec.Name := '               ';        { Clear out any old garbage          }
  129.    Rec.SSN := '         ';
  130.  
  131.    if (not eoln(input)) then
  132.       begin
  133.          read(input,Comm);               { Get the command to be performed    }
  134.          read(input,ch);
  135.  
  136.          for Index := 1 to NameLen do    { Get the name                       }
  137.             begin
  138.                read(input,ch);
  139.                Rec.Name[Index] := ch
  140.             end;
  141.  
  142.          read(input,ch);
  143.  
  144.          for Index := 1 to SSNLen do    { Get the social sercurity number     }
  145.             begin
  146.                read(input,ch);
  147.                Rec.SSN[Index] := ch
  148.             end;        
  149.  
  150.          readln(input);                 { Some clean up for next record       }
  151.       end
  152. end;  { procedure BuildRecord }
  153.  
  154.  
  155.  
  156. procedure CopyRecords(var To   : TreeType;
  157.                           From : TreeType);
  158.  
  159. {===========================================}
  160. {                                           }
  161. {  This procedure copies the needed         }
  162. {  information from the "From" variable to  }
  163. {  the "To" variable.                       }
  164. {  (i.e. copies name and SSN )              }
  165. {                                           }
  166. {===========================================}
  167.  
  168. begin
  169.    To.Name := From.Name;
  170.    To.SSN  := From.SSN;
  171. end;  { procedure CopyRecords }
  172.  
  173.  
  174.  
  175. function LessSSN(Old : TreeType;
  176.                  New : TreeType) : boolean;
  177.  
  178. {=========================================}
  179. {                                         }
  180. {  This function compare the two Socaial  }
  181. {  Security Numbers and returns TRUE if   }
  182. {  the "Old" SSN number is less that the  }
  183. {  "New" SSN number.                      }
  184. {                                         }
  185. {=========================================}
  186.  
  187. begin
  188.    LessSSN := (Old.SSN < New.SSN)
  189. end;  { function LessSSN }
  190.  
  191.  
  192.  
  193. function LessNAME(Old : TreeType;
  194.                   New : TreeType) : boolean;
  195.  
  196. {==========================================}
  197. {                                          }
  198. {  This function compares the two names    }
  199. {  and returns TRUE if the "Old" name is   }
  200. {  less than the "New" name.               }
  201. {                                          }
  202. {==========================================}
  203.  
  204. begin
  205.   LessNAME := (Old.Name < New.Name)
  206. end;  { function LessNAME }
  207.  
  208.  
  209.  
  210. function GreaterSSN(Old : TreeType;
  211.                     New : TreeType) : boolean;
  212.  
  213. {============================================}
  214. {                                            }
  215. {  This function compares the two Socaial    }
  216. {  Security Numbers and returns TRUE if the  }
  217. {  "Old" SSN number is greater than the      }
  218. {  "New" SSN number.                         }
  219. {                                            }
  220. {============================================}
  221.  
  222. begin
  223.    GreaterSSN := (Old.SSN > New.SSN)
  224. end;  { function GreaterSSN }
  225.  
  226.  
  227.  
  228. function GreaterNAME(Old : TreeType;
  229.                      New : TreeType) : boolean;
  230.  
  231. {=============================================}
  232. {                                             }
  233. {  This function compares the two Names and   }
  234. {  returns TRUE if the "Old" name is greater  }
  235. {  than the "New" name.                       }
  236. {                                             }
  237. {=============================================}
  238.  
  239. begin
  240.    GreaterNAME := (Old.Name > New.Name)
  241. end;  { function GreaterNAME }
  242.  
  243.  
  244.  
  245. function EqualSSN(Old : TreeType;
  246.                   New : TreeType) : boolean;
  247.  
  248. {==========================================}
  249. {                                          }
  250. {  This function compares the two Socaial  }
  251. {  Security Numbers and returns TRUE if    }
  252. {  if the "Old" SSN number is equal to the }
  253. {  "New" SSN number.                       }
  254. {                                          }
  255. {==========================================}
  256.  
  257. begin
  258.    EqualSSN := (Old.SSN = New.SSN)
  259. end;  { function EqualSSN }
  260.  
  261.  
  262.  
  263. function EqualNAME(Old : TreeType;
  264.                    New : TreeType) : boolean;
  265.  
  266. {===========================================}
  267. {                                           }
  268. {  This function compares the two names and }
  269. {  returns TRUE if the "Old" name is equal  }
  270. {  to the "New" name.                       }
  271. {                                           }
  272. {===========================================}
  273.  
  274. begin
  275.   EqualNAME := (Old.Name = New.Name)
  276. end;  { function EqualNAME }
  277.     
  278.  
  279.  
  280. procedure PrintSSN(Rec    : TreeType;
  281.                    Indent : integer);
  282.  
  283. {===================================}
  284. {                                   }
  285. {  This procedure prints the SSN #  }
  286. {  in the record.  It prints a      }
  287. {  boarder around the key as well   }
  288. {  as displaying the balance        }
  289. {  indicators.  They are as         }
  290. {  follows:                         }
  291. {          -1  -- Left              }
  292. {           0  -- Equal             }
  293. {          +1  -- Right             }
  294. {                                   }
  295. {===================================}
  296.  
  297. const
  298.    Line = '+----+----------------+-----------------------+';
  299.  
  300. begin
  301.    write(output,' ':Indent);
  302.    writeln(output,Line);
  303.    write(output,' ':Indent);
  304.    write(output,'| ');
  305.    if Rec.Condition = 0 then
  306.       write(' 0')
  307.    else if Rec.Condition = +1 then
  308.       write('+1')
  309.    else 
  310.       write('-1');
  311.    write(output,' | Key: ',Rec.SSN,' | Data: ',Rec.Name,' |');
  312.    write(output,' Level = ',(Indent div Offset)+1:1);
  313.    writeln(output);
  314.    write(output,' ':Indent);
  315.    writeln(output,Line)
  316. end;  {procedure PrintSSN }
  317.  
  318.  
  319.  
  320. procedure PrintNAME(Rec    : TreeType;
  321.                     Indent : integer);
  322.  
  323. {===================================}
  324. {                                   }
  325. {  This procedure prints the name   }
  326. {  in the record.  It prints a      }
  327. {  boarder around the key as well   }
  328. {  as displaying the balance        }
  329. {  indicators.  They are as         }
  330. {  follows:                         }
  331. {          -1  -- Left              }
  332. {           0  -- Equal             }
  333. {          +1  -- Right             }
  334. {                                   }
  335. {===================================}
  336.  
  337. const
  338.    Line = '+----+----------------------+-----------------+';
  339.  
  340. begin
  341.    write(output,' ':Indent);
  342.    writeln(output,Line);
  343.    write(output,' ':Indent);
  344.    write(output,'| ');
  345.    if Rec.Condition = 0 then
  346.       write(' 0')
  347.    else if Rec.Condition = +1 then
  348.       write('+1')
  349.    else 
  350.       write('-1');
  351.    write(output,' | Key: ',Rec.Name,' | Data: ',Rec.SSN,' |');
  352.    write(output,' Level = ',(Indent div Offset)+1:1);
  353.    writeln(output);
  354.    write(output,' ':Indent);
  355.    writeln(output,Line)
  356. end;  {procedure PrintNAME }
  357.  
  358.  
  359.  
  360. procedure PrintTree(T         : TreePointer;
  361.                     Index     : integer; 
  362.                     procedure Print(Rec : TreeType;Indent : integer));
  363.  
  364. {====================================================================}
  365. {                                                                    }
  366. {  This is a recursive print tree routine.  It recursivley travels   }
  367. {  down the tree and prints the tree inorder.  This allows us to see }
  368. {  what the tree looked like and where the nodes are with respect to }
  369. {  each other.  The "Offset" used in this procedure is used to       }
  370. {  displace each node so it can be seen easier in relation to its    }
  371. {  parent and its children.  The "Print" procedure does the actual   }
  372. {  printing of the node.  This allows us to use the same routine to  }
  373. {  to print trees which have been keyed on a different fields.  The  }
  374. {  outputed tree will have been shifted left 90 degrees.             }
  375. {                                                                    }
  376. {====================================================================}
  377.  
  378. begin
  379.    if T <> nil then
  380.       begin
  381.          PrintTree(T^.Right,Index + Offset,Print);
  382.          Print(T^,Index);
  383.          PrintTree(T^.Left, Index + Offset,Print);
  384.       end
  385. end;  { procedure PrintTree } 
  386.  
  387.  
  388.  
  389. procedure DumpTree(T       : TreePointer;
  390.                    procedure Print(Rec : TreeType;Indent : integer));
  391.  
  392. {===================================================================}
  393. {                                                                   }
  394. {  This is the main print tree routine which prints a small header  }
  395. {  and then calls the "PrintTree" routine to display the actual     }
  396. {  tree.                                                            }
  397. {                                                                   }
  398. {===================================================================}
  399.  
  400. begin
  401.    writeln(output,'Dumping tree');
  402.    writeln(output,'----------------');
  403.    PrintTree(T,0,Print);
  404.    writeln(output,'----------------');
  405. end;  { procedure DumpTree }
  406.  
  407.  
  408.  
  409. procedure PrintKey(Rec     : TreeType;
  410.                    KeyName : boolean);
  411.  
  412. {====================================}
  413. {                                    }
  414. {  This procedure outputs the key    }
  415. {  in each record depending on what  }
  416. {  "KeyName" was set to.  If it is   }
  417. {  TRUE then it prints the name else }
  418. {  it prints the social security     }
  419. {  number.                           }
  420. {                                    }
  421. {====================================}
  422.  
  423. begin
  424.    if KeyName then
  425.       writeln(output,Rec.Name)
  426.    else
  427.       writeln(output,Rec.SSN)
  428. end;  { procedure PrintKey }
  429.  
  430.  
  431. {-----------------------------------------------------------------------------}
  432. {                                                                             }
  433. {                         S T A C K   R O U T I N E S                         }
  434. {                                                                             }
  435. {-----------------------------------------------------------------------------}
  436.  
  437.  
  438. procedure CreateStack(var S : Stack);
  439.  
  440. {===================================}
  441. {                                   }
  442. {  Very simple routine to init. the }
  443. {  stack to nil.                    }
  444. {                                   }
  445. {===================================}
  446.  
  447. begin
  448.    S := nil
  449. end;  { procedure CreateStack }
  450.  
  451.  
  452.  
  453. procedure DumpStack(S : Stack);
  454.  
  455. {=============================}
  456. {                             }
  457. {  This routine dumps the     }
  458. {  contents of the stack.     }
  459. {  It was used as a debugging }
  460. {  aid.  It has no major      }
  461. {  value to the program other }
  462. {  than being used when de-   }
  463. {  bugging the program.       }
  464. {                             }
  465. {=============================}
  466.  
  467. var
  468.    sk : StackPtr;
  469.  
  470. begin
  471.    writeln(output,'---------');
  472.    sk := S;
  473.    while sk <> nil do
  474.       begin
  475.         writeln(output,sk^.Ptr^.Name);
  476.         sk := sk^.Next;
  477.       end;
  478.    writeln(output,'----------');
  479. end;  { procedure DumpStack }
  480.  
  481.  
  482.  
  483. procedure Push(var S : Stack;
  484.                var P : TreePointer);
  485.  
  486. {==================================}
  487. {                                  }
  488. {  This procedure pushes the       }
  489. {  "P" pointer onto the stack "S". }
  490. {                                  }
  491. {==================================}
  492.  
  493. var
  494.    NewNode : StackPtr;
  495.  
  496. begin
  497.    new(NewNode);
  498.    NewNode^.Ptr := P;
  499.    NewNode^.Next := S;
  500.    S := NewNode;
  501. end;  { procedure Push }
  502.  
  503.  
  504.  
  505. function IsEmpty(S : Stack) : boolean;
  506.  
  507. {====================================}
  508. {                                    }
  509. {  This procedure checks to see if   }
  510. {  the stack "S" is empty or not.    }
  511. {  It returns TRUE if the stack is   }
  512. {  empty.                            }
  513. {                                    }
  514. {====================================}
  515.  
  516. begin
  517.    IsEmpty := (S = nil);
  518. end;  { procedure IsEmpty }
  519.  
  520.  
  521.  
  522. function Pop(var S : Stack) : TreePointer;
  523.  
  524. {========================================}
  525. {                                        }
  526. {  This function returns the top most    }
  527. {  pointer from the stack.  If the stack }
  528. {  is empty it will return a nil         }
  529. {  pointer.                              }
  530. {                                        }
  531. {========================================}
  532.  
  533. var
  534.    DelNode : StackPtr;
  535.  
  536. begin
  537.    if S <> nil then                         { Check is stack is empty         }
  538.       begin
  539.          DelNode := S;
  540.          Pop := DelNode^.Ptr;               { Get pointer from stack          }
  541.          S := S^.Next;
  542.          dispose(DelNode)                   { Dispose of old pointer location } 
  543.       end
  544.    else
  545.       Pop := nil;                           { Stack was empty, so return nil  }
  546. end;  { function Pop }
  547.  
  548.  
  549. {-----------------------------------------------------------------------------}
  550. {                                                                             }
  551. {                          A V L    R O U T I N E S                           }
  552. {                                                                             }
  553. {-----------------------------------------------------------------------------}
  554.  
  555. { --                                                                          }
  556. { --  Both the InsertAVL and DeleteAVL routines were taken out of two         }
  557. { --  books and were modefied for our purpose.                                }
  558. { --                                                                          }
  559. { --  The InsertAVL routine was taken from:                                   }
  560. { --    "Data Structures, Algorithms, and Program Style" by James F. Korsh    }
  561. { --                                                                          }
  562. { --  The DeleteAVL routine was taken from:                                   }
  563. { --    "Data Structures in Pascal" by Edward M. Reingold & Wilfred J. Hansen }
  564. { --                                                                          }
  565. { --  DESIGN COMMENTS:                                                        }
  566. { --     In this implementation of AVL-trees I use two routines               }
  567. { --     (i.e. InsertAVL & DeleteAVL) that have two different philosophies    }
  568. { --     behind them.  One is designed recursivley and the other is           }
  569. { --     nonrecursive.  I tried to implement the delete routine               }
  570. { --     recursivly  but could not get it working.  So I used a non-          }
  571. { --     recursive procedure and stored the path to the node on a stack.      }
  572. { --     Both routines are designed so that if using different keys to search }
  573. { --     the tree, the routines do not have to be rewritten for each key.     }
  574. { --     Only the comparison routines (i.e. GreaterThan, Equal, & LessThan)   }
  575. { --     would have to be rewritten                                           }
  576. { --                                                                          }
  577.  
  578.  
  579. procedure Create(var T : TreePointer);
  580.  
  581. {====================================}
  582. {                                    }
  583. {  This init.'s the tree.  Sets it   }
  584. {  to nil.                           }
  585. {                                    }
  586. {====================================}
  587.  
  588. begin
  589.    T := nil
  590. end;  { procedure Create } 
  591.  
  592.  
  593.  
  594.  
  595. procedure InsertAVL(var       T                               : TreePointer;
  596.                               Rec                             : TreeType;
  597.                     var       Increase                        : integer;
  598.                     function  LessThan   (New,Old : TreeType) : boolean;
  599.                     function  GreaterThan(New,Old : TreeType) : boolean);
  600.  
  601. {=======================================================================}
  602. {                                                                       }
  603. {  This procedure is a recursive insert into a binary search tree.      }
  604. {  While inserting the item, it will keep the tree balanced that no two } 
  605. {  sibling subtrees differ in hight by more than 1.  If it does it will }
  606. {  rotate the subtrees to keep the tree balanced.  The procedure uses   }
  607. {  the functions "LessThan" & "GreaterThan" so that the same routine    }
  608. {  can be used on trees which have been keyed of different fields.  The }
  609. {  variable "Increase" is used to indicate if there was a change in     }
  610. {  hight when the record was inserted into the tree.                    }
  611. {  This procedure has a couble of local procedures that it uses.  They  }
  612. {  are:                                                                 }
  613. {     Reset1Balance     - Resets one balance indicater to 0 (i.e.equal) }
  614. {     Reset2Balances    - Resets two balance indicators depending on    }
  615. {                         what the previous indicators were.            }
  616. {     CreateNode        - Creates a node and inits. everything in node  }
  617. {     RotateRight       - Rotates the nodes right                       }
  618. {     RotateLeft        - Rotates the nodes left                        }
  619. {     DoubleRotateRight - Rotates the nodes right                       }
  620. {     DoubleRotateLeft  - Rotates the nodes left                        }
  621. {                                                                       }
  622. {=======================================================================} 
  623.  
  624. var 
  625.    Q : TreePointer;  { -- A temporary pointer                                 }
  626.  
  627.  
  628.      procedure Reset1Balance(Q : TreePointer);
  629.  
  630.      {---------------------------------------}
  631.      {                                       }
  632.      {  This procedure resets the balance    }
  633.      {  indicator of "Q" to 0, meaning set-  }
  634.      {  ting it to equal.                    }
  635.      {                                       }
  636.      {---------------------------------------}
  637.  
  638.      begin
  639.         Q^.Condition := 0
  640.      end; { procedure Reset1Balance }
  641.  
  642.  
  643.      procedure Reset2Balances(Q : TreePointer;
  644.                               T : TreePointer;
  645.                               P : TreePointer);
  646.  
  647.      {----------------------------------------}
  648.      {                                        }
  649.      {  This procedure set the balance        }
  650.      {  indicators such, that if "T" was      }
  651.      {  "less than" it will set the indicator }
  652.      {  of the right subtree to "greater      }
  653.      {  than" otherwise it sets the right     }
  654.      {  subtree to "equal".  After that it    }
  655.      {  checks "T" if it was "greater than"   }
  656.      {  it sets the right subtree's           }
  657.      {  indicator to "less than" otherwise    }
  658.      {  it sets it to "equal".                }
  659.      {                                        }
  660.      {----------------------------------------}
  661.  
  662.      begin
  663.         if T^.Condition = -1 then         { Check root for LESS THAN          }
  664.            P^.Condition := +1             { Set right subtree to GREATER      }
  665.         else
  666.            P^.Condition := 0;             { Else set right subtree to EQUAL   }
  667.  
  668.         if T^.Condition = +1 then         { Check root again for GREATER THAN }
  669.            Q^.Condition := -1             { Set left subtree to LESS THAN     }
  670.         else
  671.            Q^.Condition := 0              { Else set left subtree to EQUAL    }
  672.      end;  { procedure Reset2Balances }
  673.  
  674.  
  675.      procedure CreateNode(    Rec : TreeType;
  676.                           var P   : TreePointer);
  677.  
  678.      {------------------------------------------}
  679.      {                                          }
  680.      {  This creates a node and puts the cont-  }
  681.      {  tents on newly read info. into the node }
  682.      {  and sets the balance indicator to       }
  683.      {  EQUAL, since it must be a leaf node.    }
  684.      {                                          }
  685.      {------------------------------------------}
  686.  
  687.      begin
  688.         new(P);                    { Create node                              }
  689.         CopyRecords(P^,Rec);       { Copy data into node                      }
  690.         P^.Right := nil;
  691.         P^.Left := nil;
  692.         P^.Condition := 0          { Set leaf node balance indicator to EQUAL }
  693.      end;  { procedure CreaseNode}
  694.  
  695.  
  696.      procedure RotateRight(var LocalRoot : TreePointer);
  697.  
  698.      {-------------------------------------------------}
  699.      {                                                 }
  700.      {  This rotates the nodes right.  Has the effect  }
  701.      {  as follows:                                    }
  702.      {              A <- LocalRoot      B <- LocalRoot }
  703.      {            /   \               /   \            }
  704.      {          B       4           C       A          }
  705.      {        /   \               /   \   /   \        }
  706.      {      C       3           1      2 3     4       }
  707.      {    /   \                                        }
  708.      {  1       2                                      }
  709.      {          before                after            }
  710.      {                                                 }
  711.      {-------------------------------------------------}
  712.  
  713.      var
  714.         Q : TreePointer;                   { -- A temporary pointer holder    }
  715.  
  716.      begin
  717.         if DEBUG then                      { Print message if debug on        }
  718.            writeln(output,'Rotate Right');
  719.  
  720.         Q := LocalRoot^.Left;              { Save pointer to left node        }
  721.         LocalRoot^.Left := Q^.Right;       { Get pointer from left node and   }
  722.                                            {  and store it in node            }
  723.         Q^.Right := LocalRoot;             { Have pointer in left node point  }
  724.                                            {  to "LocalRoot" node             }
  725.         LocalRoot := Q;                    { Now change "LocalRoot" to point  }
  726.                                            {  to left node                    }
  727.      end;  { procedure RotateRight }
  728.  
  729.  
  730.      procedure RotateLeft(var LocalRoot : TreePointer);
  731.  
  732.      {------------------------------------------------}
  733.      {                                                }
  734.      {  This rotates the nodes left.  Has the effect  }
  735.      {  as follows:                                   }
  736.      {                                                }
  737.      {     A <- LocalRoot              B <- LocalRoot }
  738.      {   /   \                       /   \            }
  739.      { 1       B                   A       C          }
  740.      {       /   \               /   \   /   \        }
  741.      {     2       C           1      2 3     4       }
  742.      {           /   \                                }
  743.      {         3       4                              }
  744.      {      before                    after           }
  745.      {                                                }
  746.      {------------------------------------------------}
  747.  
  748.      var
  749.         Q : TreePointer;                   { -- A temporary pointer holder    }
  750.  
  751.      begin
  752.         if DEBUG then                      { Print message if debug on        }
  753.            writeln(output,'Rotate Left ');
  754.  
  755.         Q := LocalRoot^.Right;             { Save pointer to right node       }
  756.         LocalRoot^.Right := Q^.Left;       { Get pointer from right node      }
  757.                                            {  and sore it in node             }
  758.         Q^.Left := LocalRoot;              { Have pointer in left node point  }
  759.                                            {  to "LocalRoot" node             }
  760.         LocalRoot := Q;                    { Now change "LocalRoot" to point  }
  761.                                            {  to left node                    } 
  762.      end;  { procedure RotateLeft }
  763.  
  764.  
  765.      procedure DoubleRotateRight(var LocalRoot : TreePointer);
  766.  
  767.      {-------------------------------------------------------}
  768.      {                                                       }
  769.      {  This uses two rotations to balance the tree.  First  }
  770.      {  it rotates left, then it rotates right.  This has    }
  771.      {  the effect as follows:                               }
  772.      {                                                       }
  773.      {         A <- LocalRoot               C <- LocalRoot   }
  774.      {       /   \                        /   \              }
  775.      {     B       4                    B       A            }
  776.      {   /   \                        /   \   /   \          }
  777.      { 1       C                    1      2 3      4        }
  778.      {       /   \                                           }
  779.      {     2       3                                         }
  780.      {       before                        after             }
  781.      {                                                       }
  782.      {-------------------------------------------------------}
  783.  
  784.      begin
  785.         if DEBUG then                   { Pint message if debug on            }
  786.            writeln(output,'Double Rotate');
  787.  
  788.         RotateLeft(LocalRoot^.Left);    { First rotate left subtree left      }
  789.         RotateRight(LocalRoot)          { Rotate around "LocalRoot" right     }
  790.      end;  { procedure DoubleRotateRight }
  791.  
  792.      
  793.      procedure DoubleRotateLeft(var LocalRoot : TreePointer);
  794.  
  795.      {------------------------------------------------------}
  796.      {                                                      }
  797.      {  This uses two rotations to balance the tree.  First }
  798.      {  it rotates right, then it rotates left.  This has   }
  799.      {  the effect as follows:                              }
  800.      {                                                      }
  801.      {      A  <- LocalRoot             C  <- LocalRoot     }
  802.      {    /   \                      /    \                 }
  803.      {  1       B                  A        C               }
  804.      {        /   \              /   \    /   \             }
  805.      {      C       4          1       2 3      4           }
  806.      {    /   \                                             }
  807.      {  2       3                                           }
  808.      {      before                    after                 }
  809.      {                                                      }
  810.      {------------------------------------------------------}
  811.  
  812.      begin
  813.         if DEBUG then                     { Print message if debug on         }
  814.            writeln(output,'Double Rotate');
  815.  
  816.         RotateRight(LocalRoot^.Right);    { First rotate Right subtree        }
  817.         RotateLeft(LocalRoot)             { Rotate around "LocalRoot" left    }
  818.      end;  { procedure DoubleRotateLeft }
  819.  
  820.  
  821. begin
  822.    if T = nil then                                      { Check to see if we  }
  823.       begin                                             {  are at a leaf.     }
  824.         CreateNode(Rec,T);                              { Create the node.    }
  825.         Increase := 1                                   { Have increase in    }
  826.       end                                               {  depth.             }
  827.    else
  828.       if LessThan(Rec,T^) then                          { If lessthan go down }
  829.          begin                                          {  tree left.         }
  830.             InsertAVL(T^.Left,Rec,Increase,LessThan,GreaterThan);
  831.             if Increase = 1 then                        { If change in depth  }
  832.                case T^.Condition of                     {  rebalbance.        }
  833.                   0  : T^.Condition := -1;              { Change balance to   }
  834.                   +1 : begin                            {  LESS THAN.         }
  835.                           T^.Condition := 0;            { Change balance to   }
  836.                           Increase := 0;                {  EQUAL and no       }
  837.                        end;                             {  change in depth.   }
  838.                   -1 : begin
  839.                           Q := T^.Left;
  840.                           if LessThan(Rec,Q^) then      { If lessthan left    }
  841.                              begin                      {  subtree.           }
  842.                                 RotateRight(T);         { Rotate right and    }
  843.                                 Reset1Balance(T^.Right) {  reset balance.     } 
  844.                              end
  845.                           else
  846.                              begin
  847.                                 DoubleRotateRight(T);   { Must rotate right   }
  848.                                 Reset2Balances(Q,T,T^.Right)
  849.                              end;
  850.                           T^.Condition := 0;            { Set balance EQUAL.  }
  851.                           Increase := 0                 { No inc. in depth.   } 
  852.                        end
  853.                 end
  854.          end
  855.       else
  856.          if GreaterThan(Rec,T^) then                    { If greater than     }
  857.             begin                                       {  go down tree right.}
  858.                InsertAVL(T^.Right,Rec,Increase,LessThan,GreaterThan);
  859.                if Increase = 1 then                     { If change in depth  }
  860.                   case T^.Condition of                  {  rebalance.         }
  861.                      0  : T^.Condition := +1;           { Change balance to   }
  862.                     -1  : begin                         {  GREATER THAN       }
  863.                              T^.Condition := 0;         { Change balance to   }
  864.                              Increase := 0;             {  EQUAL and no       }
  865.                           end;                          {  increase in depth. }
  866.                      +1 : begin
  867.                              Q := T^.Right;
  868.                              if GreaterThan(Rec,Q^) then { If greater than    }
  869.                                 begin                    {  right subtree.    }
  870.                                    RotateLeft(T);        { Rotate left and    }
  871.                                    Reset1Balance(T^.Left); { reset balance    }
  872.                                 end
  873.                              else
  874.                                 begin
  875.                                    DoubleRotateLeft(T);  { Must rotate left   }
  876.                                    Reset2Balances(T^.Left,T,Q);
  877.                                 end;
  878.                              T^.Condition := 0;          { Set balance EQUAL  }
  879.                              Increase := 0               { No inc. in depth   }
  880.                           end
  881.                   end
  882.             end
  883. end; { procedure InsertAVL }    
  884.  
  885.  
  886.  
  887. procedure Delete(var      S                               : Stack;
  888.                           T                               : TreePointer;
  889.                           Rec                             : TreeType;
  890.                  function LessThan   (Old,New : TreeType) : boolean;
  891.                  function GreaterThan(Old,new : TreeType) : boolean;
  892.                  var      Success                         : boolean);
  893.  
  894. {===================================================================}
  895. {                                                                   }
  896. {  This procedure deletes the given record.  It does not actually   }
  897. {  delete the node, but saves the path to the deleted node on the   }
  898. {  stack and does any reschuffling of nodes if needed.              }
  899. {  This procedure calls one local routine called:                   }
  900. {    DelItem -  This is called when we have to non nil children.    }
  901. {               It then finds the node that replaces our deleted    }
  902. {               node.                                               }
  903. {                                                                   }
  904. {===================================================================}
  905.  
  906.  
  907. var
  908.    Replace : TreePointer;
  909.  
  910.  
  911.      procedure DelItem(var S           : Stack;
  912.                        var T           : TreePointer;
  913.                        var ReplaceItem : TreePointer;
  914.                        var Success     : boolean);
  915.      
  916.      {-------------------------------------------}
  917.      {                                           }
  918.      {  This procedure is called when we had two }
  919.      {  children that were not nil.  In that     }
  920.      {  case we take the largest value from the  }
  921.      {  left tree.  This routine finds that      }
  922.      {  largest value and returns a pointer to   }
  923.      {  it.  Success is set to false if item can }
  924.      {  not get the pointer                      }
  925.      {                                           }
  926.      {-------------------------------------------} 
  927.  
  928.      begin
  929.         if T <> nil then
  930.            begin
  931.               Push(S,T);                 { Save the path we are taking        }
  932.               if (T^.Right= nil) then    { If can't go any further right then }
  933.                  begin                   {  return pointer to node            }
  934.                     ReplaceItem := T;
  935.                     Success := true;
  936.                  end
  937.               else                       { Keep searching down right branch   }
  938.                  DelItem(S,T^.Right,ReplaceItem,Success);  
  939.            end
  940.         else
  941.            Success := false
  942.      end;
  943.  
  944.                         
  945. begin
  946.    if LessThan(Rec,T^) then                  { If lessthan then save path on  }
  947.       begin                                  {  stack and go down left branch }
  948.          Push(S,T);
  949.          Delete(S,T^.Left,Rec,LessThan,GreaterThan,Success)
  950.       end
  951.    else if GreaterThan(Rec,T^) then          { If greather-than then save     }
  952.       begin                                  {  path on stack and go down     }
  953.          Push(S,T);                          {  right branch.                 }
  954.          Delete(S,T^.Right,Rec,LessThan,GreaterThan,Success);
  955.       end
  956.    else 
  957.       begin                                  { Must have found item           }
  958.          Push(S,T);
  959.          if T^.Left <> nil then              { Search for largest value in    }
  960.             begin                            {  left subtree.                 }
  961.                DelItem(S,T^.Left,Replace,Success);
  962.                if Success then               { If found then copy into        }
  963.                   CopyRecords(T^,Replace^)   {  "deleted" node.               }
  964.                else
  965.                   begin                           { If not found...           }
  966.                      while T^.Left <> nil do
  967.                         begin                     { Move all nodes to left    }
  968.                            CopyRecords(T^,T^.Left^); {  one position.         }
  969.                            T := T^.Left;
  970.                            Push(S,T);             { Also save position on     }
  971.                         end;                      {  stack.                   }
  972.                   end   
  973.              end
  974.          else
  975.              begin
  976.                 while T^.Right <> nil do 
  977.                    begin                          { Move all nodes to right   }
  978.                       CopyRecords(T^,T^.Right^);  {  one position.            }
  979.                       T := T^.Right;
  980.                       Push(S,T);                  { Save position on stack.   }
  981.                    end
  982.              end;   
  983.          Success := true                          
  984.       end
  985. end;  { procedure Delete }
  986.  
  987.  
  988.  
  989. procedure DeleteAVL(var      T                               : TreePointer;
  990.                     var      S                               : Stack);
  991.  
  992. {======================================================================}
  993. {                                                                      }
  994. {  This is a non-recursive delete procedure.  This procedure deletes   }
  995. {  a node from a binary search tree and makes sure that it keeps the   }
  996. {  tree balanced.  It does this by making sure that no two sibling     }
  997. {  subtrees differ in hight by more that one.  To accoplish this it    }
  998. {  rotates the nodes around to keep them balanced.                     } 
  999. {  The "S" variable holds the stack which containd a pointer to every  } 
  1000. {  node that was visited to get to the deleted node.  The routine      }
  1001. {  checks the balance of each node that was visited when deleting      }
  1002. {  the node and rebalances the tree at that node if needed.            }
  1003. {  This rprocedure has a couple of local procedures that it uses.      }
  1004. {  The are:                                                            }
  1005. {       DeleteRotateLeft        - Rotates the nodes left               }
  1006. {       DeleteRotateRight       - Rotate the nodes right               }
  1007. {       DeleteDoubleRotateLeft  - Rotate nodes left                    }
  1008. {       DeleteDoubleRotateRight - Rotate nodes right                   }
  1009. {                                                                      }
  1010. {======================================================================}
  1011.  
  1012. var
  1013.    Current   : TreePointer;  { -- Pointer to current node working on          }
  1014.    Child     : TreePointer;  { -- Pointer is child of Current pointer         }
  1015.    Bereft    : TreePointer;  { -- Pointer to parent's child being deleted     }
  1016.  
  1017.    Balancing : boolean;      { -- If still balancing the tree                 }
  1018.    WasLeft   : boolean;      { -- If deleting left or right child of "Bereft" }
  1019.  
  1020.  
  1021.      procedure DeleteRotateLeft(var T         : TreePointer;
  1022.                                 var S         : Stack;
  1023.                                 var LocalRoot : TreePointer);
  1024.  
  1025.      {------------------------------------------------------}
  1026.      {                                                      }
  1027.      {  This rotates the nodes left.  Has the effect as     }
  1028.      {  follows:                                            }
  1029.      {                                                      }
  1030.      {        A <- LocalRoot              B <- LocalRoot    }
  1031.      {      /   \                       /   \               }
  1032.      {    1       B                   A       C             }
  1033.      {          /   \               /   \   /   \           }
  1034.      {        2       C           1      2 3     4          }
  1035.      {              /   \                                   }
  1036.      {            3       4                                 }
  1037.      {         before                    after              }
  1038.      {                                                      }
  1039.      {  Once done with the rotation it gets the next        }
  1040.      {  pointer from the stack and corrects its pointer to  }
  1041.      {  to point to the newly rotated subtree.              }
  1042.      {                                                      }
  1043.      {------------------------------------------------------}
  1044.  
  1045.      var
  1046.         TempNode : TreePointer;              { -- A temporary pointer holder  }
  1047.  
  1048.      begin
  1049.         if DEBUG then                        { Print message if debug on      }
  1050.            writeln(output,'Rotate Left');
  1051.  
  1052.         TempNode := LocalRoot^.Right;        { Save pointer to right node.    }
  1053.         LocalRoot^.Right := TempNode^.Left;  { Get pointer from right node    }
  1054.                                              {  and store it in node .        }
  1055.         TempNode^.Left := LocalRoot;         { Have pointer in left node      }
  1056.                                              {  point to "LocalRoot" node.    }
  1057.         LocalRoot := TempNode;               { Now change "LocalRoot" to      } 
  1058.                                              {  point to left node.           }
  1059.         
  1060.         { Now fix the pointer to this subtree.  Get him from stack and fix    }
  1061.         { his pointer to point to this subtree.                               }
  1062.  
  1063.         if IsEmpty(S) then                   { Check if this is the root      }
  1064.            T := LocalRoot                    { Have the root point to this    }
  1065.         else                                 {  subtree.                      }
  1066.            begin
  1067.               TempNode := Pop(S);            { Get pointer to this node       }
  1068.               if TempNode^.Right = LocalRoot^.Left then { Find pointer to     }
  1069.                  TempNode^.Right := LocalRoot           {  this subtree       }
  1070.               else                                      {  and fix that       }
  1071.                  TempNode^.Left := LocalRoot;           {  pointer.           }
  1072.               Push(S,TempNode);                         { And save it on the  }
  1073.            end                                          {  stack again.       }
  1074.      end;  { procedure DeleteRotateLeft }
  1075.  
  1076.  
  1077.      procedure DeleteRotateRight(var T         : TreePointer;
  1078.                                  var S         : Stack;
  1079.                                  var LocalRoot : TreePointer);
  1080.  
  1081.      {-------------------------------------------------------}
  1082.      {                                                       }
  1083.      {  This rotates the nodes right.  Has the effect as     }
  1084.      {  follows:                                             }
  1085.      {                 A <- LocalRoot      B <- LocalRoot    }
  1086.      {               /   \               /   \               }
  1087.      {             B       4           C       A             }
  1088.      {           /   \               /   \   /   \           }
  1089.      {         C       3           1      2 3     4          }
  1090.      {       /   \                                           }
  1091.      {     1       2                                         }
  1092.      {             before                after               }
  1093.      {                                                       }
  1094.      {  Once the routine has been rotated the pointer to     }
  1095.      {  this subtree must be fixed so it points to the right }
  1096.      {  node.                                                }
  1097.      {                                                       }
  1098.      {-------------------------------------------------------}
  1099.  
  1100.      var
  1101.         TempNode : TreePointer;              { -- A temporary pointer holder  }
  1102.  
  1103.      begin
  1104.         if DEBUG then                        { Print message if debug is on   }
  1105.            writeln(output,'Rotate Right');
  1106.  
  1107.         TempNode := LocalRoot^.Left;         { Save pointer to left node      }
  1108.         LocalRoot^.Left := TempNode^.Right;  { Get pointer from left node and }
  1109.                                              {  store it in node.             }
  1110.         TempNode^.Right := LocalRoot;        { Have pointer in left node      }
  1111.                                              {  point to "LocalRoot" node.    }
  1112.         LocalRoot := TempNode;               { Now change "LocalRoot" to      }
  1113.                                              {  point to left node.           }
  1114.         if IsEmpty(S) then                   { Check to see if this is root   }
  1115.            T := LocalRoot                    { Have root pointer point to     }
  1116.         else                                 {  this subtree.                 }
  1117.            begin
  1118.               TempNode := Pop(S);            { Get pointer to this node       }
  1119.               if TempNode^.Right = LocalRoot^.Right then { Find which pointer }
  1120.                  TempNode^.Right := LocalRoot            {  points here and   }
  1121.               else                                       {  fix it to point   }
  1122.                  TempNode^.Left := LocalRoot;            {  here.             }
  1123.               Push(S,TempNode)                           { Save pointer again }
  1124.            end
  1125.      end;  { procedure DeleteRotateLeft }
  1126.  
  1127.  
  1128.      procedure DeleteDoubleRotateRight(var T         : TreePointer;
  1129.                                        var S         : Stack;
  1130.                                        var LocalRoot : TreePointer);
  1131.  
  1132.      {-------------------------------------------------------------}
  1133.      {                                                             }
  1134.      {  This uses two rotations to balance the tree.  First  it    }
  1135.      {  rotates left, then it rotates right.  This has the effect  }
  1136.      {  as follows:                                                }
  1137.      {                                                             }
  1138.      {            A <- LocalRoot               C <- LocalRoot      }
  1139.      {          /   \                        /   \                 }
  1140.      {        B       4                    B       A               }
  1141.      {      /   \                        /   \   /   \             }
  1142.      {    1       C                    1      2 3      4           }
  1143.      {          /   \                                              }
  1144.      {        2       3                                            }
  1145.      {          before                        after                }
  1146.      {                                                             }
  1147.      {-------------------------------------------------------------}
  1148.  
  1149.  
  1150.      begin
  1151.         if DEBUG then                          { Print message if debug on    }
  1152.            writeln(output,'Double rotate');
  1153.  
  1154.         DeleteRotateLeft(T,S,LocalRoot^.Left); { Rotate left subtree left     }
  1155.         DeleteRotateRight(T,S,LocalRoot)       { Rotate around "LocalRoot"    }
  1156.                                                {  right.                      }
  1157.      end;  { procedure DeleteDoubleRotateRight }     
  1158.  
  1159.  
  1160.      procedure DeleteDoubleRotateLeft(var T         : TreePointer;
  1161.                                       var S         : Stack;
  1162.                                       var LocalRoot : TreePointer);
  1163.  
  1164.      {------------------------------------------------------------}
  1165.      {                                                            }
  1166.      {  This uses two rotations to balance the tree.  First it    }
  1167.      {  rotates right, then it rotates left.  This has the effect }
  1168.      {  as follows:                                               }
  1169.      {                                                            }
  1170.      {         A  <- LocalRoot             C  <- LocalRoot        }
  1171.      {       /   \                      /    \                    }
  1172.      {     1       B                  A        C                  }
  1173.      {           /   \              /   \    /   \                }
  1174.      {         C       4          1       2 3      4              }
  1175.      {       /   \                                                }
  1176.      {     2       3                                              }
  1177.      {         before                       after                 }
  1178.      {                                                            }
  1179.      {------------------------------------------------------------}
  1180.  
  1181.      begin
  1182.         if DEBUG then                            { Print message if debug on  }
  1183.             writeln(output,'Double rotate');
  1184.  
  1185.         DeleteRotateRight(T,S,LocalRoot^.Right); { Rotate Right subtree       }
  1186.         DeleteRotateLeft(T,S,LocalRoot)          { Rotate around "LocalRoot"  }
  1187.                                                  {  left.                     }
  1188.      end;  { procedure DeleteDoubleRotateLeft }
  1189.  
  1190.  
  1191. begin
  1192.    Child := Pop(S);                              { Get Child -- deleted node  }
  1193.    if IsEmpty(S) then                            { If it was root, set tree   }
  1194.       T := nil                                   {  nil.                      }
  1195.    else
  1196.       begin
  1197.          Current := Pop(S);                      { Get node to be worked on   }
  1198.          Bereft := Current;                      { This is the parent of node }
  1199.                                                  {  to be deleted             }
  1200.          WasLeft := (Child = Bereft^.Left);      { See if it was left child   }
  1201.          Balancing := true;
  1202.          while Balancing do
  1203.             begin
  1204.                if Current^.Condition = 0 then    { IF EQUAL                   }
  1205.                   begin
  1206.  
  1207.                      { RULE 1:  Deltetion from either subtree can be absorbed }
  1208.                      {          here.                                         }
  1209.  
  1210.                      if Child = Current^.Left then { If we have left child    }
  1211.                         Current^.Condition := +1   { Set it to GREATER THAN   }
  1212.                      else
  1213.                         Current^.Condition := -1;  { Else set to LESS THAN    }
  1214.                      Balancing := false            { Done with balancing      }
  1215.                   end
  1216.                else if ((Current^.Condition = +1) and (Child = Current^.Right)) or
  1217.                        ((Current^.Condition = -1) and (Child = Current^.Left)) then  
  1218.  
  1219.                   { RULE 2:  "Current" becomes balanced, but its subtree is   }
  1220.                   {          shorter so imbalance must be propagated up       }
  1221.  
  1222.                   Current^.Condition := 0          { Set to EQUAL             }
  1223.                else
  1224.                   if (Current^.Condition = +1) and (Child = Current^.Left) then
  1225.                     begin
  1226.                    
  1227.                       { RULE 3 and 4:  Have to do some rebalancing to get     }
  1228.                       {                tree back in balance                   }
  1229.  
  1230.                       if (Current^.Right^.Condition = 0) then 
  1231.                          begin                                
  1232.  
  1233.                             { If right subtree is EQUAL   }
  1234.  
  1235.                             DeleteRotateLeft(T,S,Current);    
  1236.                             Current^.Condition := -1;       { Set LESS THAN    }
  1237.                             Current^.Left^.Condition := +1; { Set GREATER THAN }
  1238.                             Balancing := false;             { Done balancing   }
  1239.                          end
  1240.                       else if (Current^.Right^.Condition = +1) then 
  1241.                          begin
  1242.  
  1243.                             { If right subtree is GREATER THAN }
  1244.  
  1245.                             DeleteRotateLeft(T,S,Current);
  1246.                             Current^.Condition := 0;          { Set EQUAL     }
  1247.                             Current^.Left^.Condition := 0;    { Set EQUAL     }
  1248.                          end
  1249.                       else if (Current^.Right^.Condition = -1) then
  1250.                          begin
  1251.  
  1252.                             { If Right subtree is LESS THAN }
  1253.  
  1254.                             DeleteDoubleRotateLeft(T,S,Current);                           
  1255.                             if Current^.Condition = 0 then
  1256.                                begin
  1257.                                 
  1258.                                   { If subtree is EQUAL }
  1259.  
  1260.                                   Current^.Left^.Condition := 0;  { Set EQUAL }
  1261.                                   Current^.Right^.Condition := 0; { Set EQUAL }
  1262.                                end
  1263.                             else if Current^.Condition = +1 then
  1264.                                begin
  1265.  
  1266.                                   { If subtree is GREATER THAN }
  1267.  
  1268.                                   Current^.Left^.Condition := -1; { Set LESS THAN }
  1269.                                   Current^.Right^.Condition := 0; { Set EQUAL     }
  1270.                                end
  1271.                             else
  1272.                                begin
  1273.  
  1274.                                   { If subtree is LESS THAN }
  1275.  
  1276.                                   Current^.Left^.Condition := 0;  { Set EQUAL        }
  1277.                                   Current^.Right^.Condition := +1 { Set GREATER THAN }
  1278.                                end;
  1279.     
  1280.                             Current^.Condition := 0;              { Set EQUAL        }
  1281.                          end
  1282.                     end 
  1283.                   else
  1284.                     begin
  1285.                        if (Current^.Left^.Condition = 0) then
  1286.                           begin
  1287.  
  1288.                              { If left subtree is EQUAL }
  1289.  
  1290.                              DeleteRotateRight(T,S,Current);
  1291.                              Current^.Condition := +1;        { Set GREATER THAN }
  1292.                              Current^.Right^.Condition := -1; { Set LESS THAN    }
  1293.                              Balancing := false;              { Done Balancing   }
  1294.                   end
  1295.                    else if (Current^.Left^.Condition = -1) then
  1296.                           begin
  1297.  
  1298.                              { If left subtree is LESS THAN }
  1299.  
  1300.                              DeleteRotateRight(T,S,Current);
  1301.                              Current^.Condition := 0;        { Set EQUAL }
  1302.                              Current^.Right^.Condition := 0; { Set EQUAL }
  1303.                           end
  1304.                        else
  1305.                           begin
  1306.  
  1307.                              { If Left subtree is GREATER THAN }
  1308.  
  1309.                              DeleteDoubleRotateRight(T,S,Current);
  1310.                              if Current^.Condition = 0 then
  1311.                                begin
  1312.  
  1313.                                   { If subtree is EQUAL }
  1314.  
  1315.                                   Current^.Left^.Condition := 0;    { Set EQUAL       }
  1316.                                   Current^.Right^.Condition := 0;   { Set EQUAL       }
  1317.                                end
  1318.                              else if Current^.Condition = -1 then
  1319.                                begin
  1320.  
  1321.                                   { If subtree is LESS THAN }
  1322.  
  1323.                                   Current^.Left^.Condition := 0;   { Set EQUAL        }
  1324.                                   Current^.Right^.Condition := +1; { Set GREATER THAN }
  1325.                                end
  1326.                              else
  1327.                                begin
  1328.  
  1329.                                   { If subtree is GREATER THAN }
  1330.  
  1331.                                   Current^.Left^.Condition := -1; { Set LESS THAN    }
  1332.                                   Current^.Right^.Condition := 0  { Set EQUAL        }
  1333.                                end;
  1334.                              Current^.Condition := 0;             { Set EQUAL        }
  1335.                           end
  1336.                     end;
  1337.  
  1338.                { The rotations may have set "Balancing" to FALSE, otherwise }
  1339.                { continue up the tree.                                      }
  1340.  
  1341.                if Balancing then
  1342.                   if IsEmpty(S) then      { Check to see if any more to check }
  1343.                      Balancing := false 
  1344.                   else
  1345.                      begin
  1346.                         Child := Current; { Make parent the child             }
  1347.                         Current := Pop(S) { Get new parent                    }
  1348.                      end
  1349.             end;
  1350.  
  1351.             { Now do the actual deleting of the node.  We check if it }
  1352.             { is the left or right child that we have to delete.      }
  1353.  
  1354.             if WasLeft then  
  1355.                begin
  1356.                   dispose(Bereft^.Left);
  1357.                   Bereft^.Left := nil
  1358.                end 
  1359.             else
  1360.                begin
  1361.                   dispose(Bereft^.Right);
  1362.                   Bereft^.Right := nil;
  1363.                end 
  1364.    end
  1365. end;  { procedure DeleteAVL }  
  1366.  
  1367.  
  1368.  
  1369. procedure DeleteNode(var      T                               : TreePointer;
  1370.                               Rec                             : TreeType;
  1371.                      function LessThan   (Old,New : TreeType) : boolean;
  1372.                      function GreaterThan(Old,New : TreeType) : boolean); 
  1373.  
  1374. {=======================================================================}
  1375. {                                                                       }
  1376. {  This is the main "Delete" procedure.  It first creates the stack     }
  1377. {  where we will save our pointers.  Then we go and delete the node     }
  1378. {  keeping track of which way we went by pushing pointers to the node   }
  1379. {  on the stack.  The we use "DeleteAVL" to rebalance and delete the    }
  1380. {  actual node.                                                         }
  1381. {                                                                       }
  1382. {=======================================================================}
  1383.  
  1384. var
  1385.    Success : boolean;
  1386.    S       : Stack;
  1387.  
  1388. begin
  1389.    CreateStack(S);
  1390.    Delete(S,T,Rec,LessThan,GreaterThan,Success);
  1391.    DeleteAVL(T,S)
  1392. end;  { procedure DeleteNode }
  1393.  
  1394.  
  1395. {---------------------------------------------------------------}
  1396. {                                                               }
  1397. {                  M A I N     P R O G R A M                    }
  1398. {                                                               }
  1399. {---------------------------------------------------------------}
  1400.  
  1401.  
  1402. begin
  1403.    Create(Tree);
  1404.  
  1405.    write(output,'Running program with DEBUG ');
  1406.    if DEBUG then
  1407.       write(output,'on')
  1408.    else
  1409.       write(output,'off');
  1410.    write(output,' and keyed on ');
  1411.    if KeyOnName then
  1412.       writeln(output,'Name')
  1413.    else
  1414.       writeln(output,'Socaial Security Number');
  1415.    writeln(output);
  1416.  
  1417.    repeat
  1418.      Comm := ' ';                            { Clear command               }
  1419.      writeln(output);
  1420.      BuildRecord(Comm,NewRec);               { Get command and new record  }
  1421.      if (Comm = 'A') or (Comm = 'a') then
  1422.         begin
  1423.  
  1424.            { Adding record to the tree. }
  1425.  
  1426.            write(output,'Inserting ==> ');
  1427.            PrintKey(NewRec,KeyOnName);
  1428.            Increase := 0;
  1429.            if KeyOnName then               { Key on name                   }
  1430.               InsertAVL(Tree,NewRec,Increase,LessNAME,GreaterNAME)
  1431.            else                            { Key on Social Security Number }
  1432.               InsertAVL(Tree,NewRec,Increase,LessSSN,GreaterSSN);
  1433.         end
  1434.      else if (Comm = 'P') or (Comm = 'p') then
  1435.         begin
  1436.  
  1437.            { Printing the tree. }
  1438.  
  1439.            if KeyOnName then               { Key on name                   }
  1440.               DumpTree(Tree,PrintNAME)
  1441.            else                            { Key on Social Security Number }
  1442.               DumpTree(Tree,PrintSSN);
  1443.         end
  1444.      else if (Comm = 'D') or (Comm = 'd') then
  1445.         begin
  1446.  
  1447.            { Deleting the record from the tree. }
  1448.  
  1449.            write(output,'Deleting ==> ');
  1450.            PrintKey(NewRec,KeyOnName);
  1451.            if KeyOnName then               { Key on Name                   }
  1452.               DeleteNode(Tree,NewRec,LessNAME,GreaterNAME)
  1453.            else                            { Key on Social Security Number }
  1454.               DeleteNode(Tree,NewRec,LessSSN,GreaterSSN);
  1455.         end
  1456.      else if (Comm = 'C') or (Comm = 'c') then
  1457.         begin
  1458.  
  1459.            { Clear the tree.  Start the tree over.  This does not    }
  1460.            { recover the previous nodes.  Mainly used when debugging }
  1461.  
  1462.            writeln(output,'Clearing tree');
  1463.            new(Tree);
  1464.            Tree := nil;
  1465.         end
  1466.    until (Comm = 'S') or (Comm = 's');
  1467. end.   
  1468.  
  1469.