home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / JUMPSRCH.ZIP / JUMPSRCH.PAS
Encoding:
Pascal/Delphi Source File  |  1986-10-22  |  8.8 KB  |  345 lines

  1. program Jump_search;
  2. {$u-,r-,k+,c-}
  3. { Marshall Brain       July 17, 1986
  4.   This program implements the Jump Search algorithm.}
  5.  
  6.  
  7. type
  8.   num_pntr=^data_rec;
  9.   jump_pntr=^jump_rec;
  10.  
  11.   {typical data record - forward and backward pointers and data}
  12.   data_rec=record
  13.      nextpntr,prevpntr : num_pntr;
  14.      num  : integer;
  15.   end;
  16.  
  17.   {A Jump Node consists of a single link forward and a
  18.    pointer to a specific data item.}
  19.   jump_rec=record
  20.     nextjump:jump_pntr;
  21.     data_pntr:num_pntr;
  22.   end;
  23.  
  24. var
  25.   tempdata,firstdata,lastdata:num_pntr;
  26.   tempjump,firstjump,lastjump:jump_pntr;
  27.   prevtimecx,prevtimedx,timedx,timecx:integer;
  28.   list_size:integer;
  29.   time:real;
  30.  
  31.   procedure fill_data_list;
  32.   {creates a double linked list of list_size elements on the
  33.    heap. Each record on the heap contains 2 pointers and the
  34.    "data", it this case a single integer.}
  35.   var x:integer;
  36.  
  37.     procedure append_to_list;
  38.     {appends the next data record to the end of the list. In a normal
  39.      program this would be replaced by insertion and deletion 
  40.      routines for the linked list.}
  41.     begin
  42.       {if no records in list, then make current record the first.}
  43.       if firstdata=nil then
  44.       begin
  45.         firstdata:=tempdata;
  46.         lastdata:=tempdata;
  47.         tempdata^.nextpntr:=nil;
  48.         tempdata^.prevpntr:=nil;
  49.       end
  50.       {otherwise append to end of list.}
  51.       else
  52.       begin
  53.         lastdata^.nextpntr:=tempdata;
  54.         tempdata^.nextpntr:=nil;
  55.         tempdata^.prevpntr:=lastdata;
  56.         lastdata:=tempdata;
  57.       end;
  58.     end;
  59.  
  60.   begin {fill_data_list}
  61.     firstdata:=nil;lastdata:=nil;
  62.     {This demo uses simple data in the linked list - a set of
  63.      consecutive integers. Note that list MUST be sorted to use
  64.      the jumping technique.}
  65.     for x:=1 to list_size do
  66.     begin
  67.       new(tempdata);
  68.       tempdata^.num:=x;
  69.       append_to_list;
  70.     end;
  71.   end;
  72.  
  73.   procedure create_jump_list;
  74.   {Given a sorted linked list, this routine will create a balanced
  75.    jumping list to use for searching.}
  76.   var y,x,jump_distance:integer;
  77.  
  78.     procedure create_jump_node;
  79.     {creates and links in a new jump node.}
  80.     begin
  81.       new(tempjump);
  82.      {point jump records data pointer at current data item.}
  83.       tempjump^.data_pntr:=tempdata;
  84.      {form linked list of jump records by appending onto end of
  85.       jump list.}
  86.       if firstjump=nil then
  87.         firstjump:=tempjump
  88.       else
  89.         lastjump^.nextjump:=tempjump;
  90.       tempjump^.nextjump:=nil;
  91.       lastjump:=tempjump;
  92.     end;
  93.  
  94.   begin {create_jump_list}
  95.    {determine optimal jump distance.}
  96.     jump_distance:=trunc(sqrt(list_size));
  97.     x:=1; y:=1;
  98.    {start with first element of data list.}
  99.     tempdata:=firstdata;
  100.     firstjump:=nil; lastjump:=nil;
  101.    {sequence through entire list.}
  102.     while y<list_size do
  103.     begin
  104.       {every sqrt(list_size) create a jump node.}
  105.       if x>=jump_distance then
  106.       begin
  107.         create_jump_node;
  108.         x:=0;
  109.       end;
  110.      {get next data item in list.}
  111.       tempdata:=tempdata^.nextpntr;
  112.       y:=y+1; x:=x+1;
  113.     end;
  114.    {create final jump node at very end of list.}
  115.     create_jump_node;
  116.   end;
  117.  
  118.   procedure jump_search(num_to_find:integer);
  119.   var found:boolean;
  120.  
  121.     procedure coarse_search;
  122.     {the coarse search jumps through the jump nodes looking for
  123.      the nearest match to the data to be found. As soon as a
  124.      jump node is found pointing to a data item >= the item
  125.      to be found, the course search stops.}
  126.  
  127.     var done:boolean;
  128.  
  129.     begin
  130.      {start at first jump node.}
  131.       tempjump:=firstjump;
  132.       done:=false;
  133.       while not done do
  134.       begin
  135.        {stop when data item >= num to be found.}
  136.         if tempjump^.data_pntr^.num>=num_to_find then
  137.           done:=true
  138.         else
  139.         begin
  140.           {Also stop course search at end of jump list (last
  141.            element in data list).}
  142.           if tempjump^.nextjump=nil then
  143.             done:=true
  144.           else
  145.             tempjump:=tempjump^.nextjump;
  146.         end;
  147.       end;
  148.     end;
  149.  
  150.     procedure fine_search;
  151.  
  152.     var stop:boolean;
  153.     {fine search then goes backwards thru every element in data
  154.      list itself until item is found or item can not exist.}
  155.  
  156.     begin
  157.      {start looking at jump node coarse search stopped at.}
  158.       tempdata:=tempjump^.data_pntr;
  159.       found:=false; stop:=false;
  160.       while not found and not stop do
  161.       begin
  162.        {if beyond possibility, stop search.}
  163.         if num_to_find>tempdata^.num then
  164.           stop:=true
  165.         else
  166.         begin
  167.           if num_to_find=tempdata^.num then
  168.             found:=true
  169.           else
  170.             tempdata:=tempdata^.prevpntr;
  171.         end;
  172.       end;
  173.       if not found then write(' not found ');
  174.     end;
  175.  
  176.   begin {jump_search}
  177.     coarse_search;
  178.     fine_search;
  179.     {at this point programmer decides what to do with the found data
  180.      item. FOUND will be true if found, and TEMPDATA will point to
  181.      found data item.}
  182.   end;
  183.  
  184.   procedure sequential_search(num_to_find:integer);
  185.   {standard sequential search routine used 
  186.    for comparison in benchmarking.}
  187.  
  188.   var stop,found:boolean;
  189.  
  190.   begin
  191.     tempdata:=firstdata;
  192.     found:=false; stop:=false;
  193.     while not found and not stop do
  194.     begin
  195.       if num_to_find<tempdata^.num then
  196.         stop:=true
  197.       else
  198.       begin
  199.         if num_to_find=tempdata^.num then
  200.           found:=true
  201.         else
  202.           tempdata:=tempdata^.nextpntr;
  203.       end;
  204.     end;
  205.   end;
  206.  
  207.   procedure beep;
  208.   begin
  209.     sound(500);
  210.     delay(1000);
  211.     nosound;
  212.   end;
  213.  
  214.   procedure get_time(var cx,dx:integer);
  215.  
  216.   var result:record ax,bx,cx,dx,bp,si,di,ds,es,flags:integer; end;
  217.  
  218.   begin
  219.     result.ax:=0;
  220.     intr($1a,result);
  221.     cx:=result.cx;dx:=result.dx;
  222.   end;
  223.  
  224.   procedure calc_time;
  225.   begin
  226.     time:=(timecx-prevtimecx)*65536.0 + 
  227.           (hi(timedx)-hi(prevtimedx))*256.0 +
  228.           (lo(timedx)-lo(prevtimedx));
  229.  
  230.     time:=time/18.2;
  231.   end;
  232.  
  233.   procedure time_searches;
  234.  
  235.   var a:integer;jtime:real;
  236.  
  237.   begin
  238.     write('  Jump Searching list.        ');
  239.     get_time(prevtimecx,prevtimedx);
  240.     a:=1;
  241.     while a<=list_size do
  242.     begin
  243.       jump_search(a);
  244.       a:=a+11;  {use prime number to avoid bias in benchmarks.}
  245.     end;
  246.     get_time(timecx,timedx);
  247.     calc_time;
  248.     writeln('    done. Time =',time:6:2);
  249.     jtime:=time;
  250.     writeln;
  251.     write('  Sequentially Searching list.');
  252.     get_time(prevtimecx,prevtimedx);
  253.     a:=1;
  254.     while a<=list_size do
  255.     begin
  256.       sequential_search(a);
  257.       a:=a+11;  {use prime number to avoid bias in benchmarks.}
  258.     end;
  259.     get_time(timecx,timedx);
  260.     calc_time;
  261.     writeln('    done. Time =',time:6:2);
  262.     writeln;
  263.     if jtime=0 then jtime:=0.05;
  264.     writeln('Jump Searching was ',time/jtime:4:1,
  265.             ' times faster for a ',list_size,
  266.             ' element list');
  267.   end;
  268.  
  269.   procedure setup;
  270.  
  271.   var error:boolean;
  272.  
  273.   begin
  274.     clrscr;
  275.     gotoxy(1,5);
  276.     writeln
  277.     ('This program will produce a benchmark comparing the time to');
  278.     writeln
  279.     ('do a number of sequential searches with a number of identical');
  280.     writeln
  281.     ('Jump Searches. You will be asked to enter a number indicating');
  282.     writeln
  283.     ('the number of elements to be placed in the linked list used');
  284.     writeln
  285.     ('for this test.  Numbers greater that 1000 can produce very');
  286.     writeln
  287.     ('long sequential searches in this test, but results are');
  288.     writeln('more dramatic for longer searches.');
  289.     writeln;
  290.     writeln('Enter the number of items to be in the linked list.  ');
  291.     write('Please type an integer less than 30000 : ');
  292.     readln(list_size);
  293.     writeln;writeln;
  294.   end;
  295.  
  296.   procedure make_linked_list;
  297.   begin
  298.     writeln;
  299.     writeln('List size for test = ',list_size);
  300.     writeln('Number of searches for test = ',list_size div 11);
  301.     writeln('All times are in seconds.');
  302.     writeln;
  303.     writeln('  Setting up linked list used for testing.');
  304.     fill_data_list;
  305.     writeln;
  306.   end;
  307.  
  308.   procedure make_jump_list;
  309.   begin
  310.     write('  Creating Jump Nodes.        ');
  311.     get_time(prevtimecx,prevtimedx);
  312.     create_jump_list;
  313.     get_time(timecx,timedx);;
  314.     calc_time;
  315.     writeln('    done. Time =',time:6:2);
  316.     writeln;
  317.   end;
  318.  
  319.   function size_ok:boolean;
  320.  
  321.   var x:real;
  322.  
  323.   begin
  324.     if maxavail<0 then x:=maxavail+65536.0 else x:=maxavail;
  325.     if x*16.0-(list_size*16.0+trunc(sqrt(list_size))*8.0)<0.0 then
  326.       size_ok:=false
  327.     else
  328.       size_ok:=true;
  329.  end;
  330.  
  331. begin {main}
  332.   setup;
  333.   if size_ok then
  334.   begin
  335.     make_linked_list;
  336.     make_jump_list;
  337.     time_searches;
  338.     beep;
  339.   end
  340.   else
  341.     writeln('Linked list created would be too large', 
  342.         ' for your available memory.');
  343. end.
  344.  
  345.