home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 3 / AACD03.BIN / AACD / Programming / sofa / archive / SmallEiffel.lha / SmallEiffel / lib_std / reverse_collection_sorter.e < prev    next >
Text File  |  1999-06-05  |  10KB  |  356 lines

  1. -- This file is  free  software, which  comes  along  with  SmallEiffel. This
  2. -- software  is  distributed  in the hope that it will be useful, but WITHOUT 
  3. -- ANY  WARRANTY;  without  even  the  implied warranty of MERCHANTABILITY or
  4. -- FITNESS  FOR A PARTICULAR PURPOSE. You can modify it as you want, provided
  5. -- this header is kept unaltered, and a notification of the changes is added.
  6. -- You  are  allowed  to  redistribute  it and sell it, alone or as a part of 
  7. -- another product.
  8. --          Copyright (C) 1994-98 LORIA - UHP - CRIN - INRIA - FRANCE
  9. --            Dominique COLNET and Suzanne COLLIN - colnet@loria.fr 
  10. --                       http://SmallEiffel.loria.fr
  11. --
  12. expanded class REVERSE_COLLECTION_SORTER[X -> COMPARABLE]
  13. --
  14. -- Some algorithms to sort any COLLECTION[COMPARABLE].
  15. --
  16. -- Elements are sorted using decreasing order: large elements 
  17. -- at the begining of the colection, small at the end (increasing
  18. -- order is implemented by class COLLECTION_SORTER).
  19. --
  20. -- How to use this expanded class :
  21. --
  22. --          local
  23. --             sorter: REVERSE_COLLECTION_SORTER[INTEGER];
  24. --             array: ARRAY[INTEGER];
  25. --          do
  26. --             array := <<1,3,2>>;
  27. --             sorter.sort(array);
  28. --             check
  29. --                sorter.is_sorted(array);
  30. --             end;
  31. --             ...
  32. --
  33.  
  34. feature
  35.  
  36.    is_sorted(c: COLLECTION[X]): BOOLEAN is
  37.          -- Is `c' already sorted ?
  38.          -- Uses infix ">=" for comparison.
  39.       require
  40.          c /= Void
  41.       local
  42.          i, c_upper: INTEGER;
  43.          elt1, elt2: X;
  44.       do
  45.          i := c.lower;
  46.          c_upper := c.upper;
  47.          Result := true;
  48.          if c_upper > i then
  49.             from
  50.                elt1 := c.item(i);
  51.             invariant
  52.                c.valid_index(i)
  53.             until
  54.                not Result or else i >= c_upper
  55.             loop
  56.                i := i + 1;
  57.                elt2 := c.item(i);
  58.                Result := elt1 >= elt2;
  59.                elt1 := elt2;
  60.             end;
  61.          end;
  62.       ensure
  63.          c.is_equal(old c.twin)
  64.       end;
  65.  
  66.   
  67.    sort(c: COLLECTION[X]) is
  68.          -- Sort `c' using the default most efficient sorting algorithm
  69.          -- already implemented.
  70.       require
  71.          c /= Void
  72.       do
  73.          if not is_sorted(c) then
  74.             quick_sort(c);
  75.          end;
  76.       ensure
  77.          c.count = old c.count;
  78.          is_sorted(c)
  79.       end;
  80.          
  81.    quick_sort(c: COLLECTION[X]) is
  82.          -- Sort `c' using the quick sort algorithm.
  83.       require
  84.          c /= Void
  85.       do
  86.         quick_sort_region(c,c.lower,c.upper);               
  87.       ensure
  88.          c.count = old c.count;
  89.          is_sorted(c)
  90.       end;
  91.  
  92.    von_neuman_sort(c: COLLECTION[X]) is
  93.          -- Sort `c' using the Von Neuman algorithm.
  94.          -- This algorithm needs to create a second collection.
  95.          -- Uses infix "<=" for comparison.
  96.       require
  97.          c /= Void
  98.       local
  99.          src, dest, tmp: COLLECTION[X];
  100.          nb, count, d_count, c_count, lower, imax: INTEGER;
  101.       do
  102.          c_count := c.count;
  103.          if c_count > 1 then
  104.             lower := c.lower;
  105.             imax := c.upper + 1;
  106.             from
  107.                count := 1;
  108.             until
  109.                count >= c_count
  110.             loop
  111.                count := count * 2;
  112.                nb := nb + 1;
  113.             end;
  114.             if nb.odd then
  115.                src := c;
  116.                dest := c.twin;
  117.             else
  118.                dest := c;
  119.                src := c.twin;
  120.             end;
  121.             from
  122.                count := 1;
  123.             variant
  124.                c_count * 2 - count
  125.             until
  126.                count >= c_count
  127.             loop
  128.                d_count := count * 2;
  129.                tmp := dest;
  130.                dest := src;
  131.                src := tmp;
  132.                von_neuman_line(src,dest,count,d_count,lower,imax);
  133.                count := d_count;
  134.             end;
  135.          end;
  136.       ensure
  137.          c.count = old c.count;
  138.          is_sorted(c)
  139.       end;
  140.  
  141.    
  142.    bubble_sort(c: COLLECTION[X]) is
  143.          -- Sort `c' using the bubble sort algorithm.
  144.          -- Uses infix ">" for comparison.
  145.       require
  146.          c /= Void
  147.       local
  148.          i, imax, imin: INTEGER;
  149.          modified: BOOLEAN;
  150.       do
  151.          from
  152.             imax := c.upper;
  153.             imin := c.lower;
  154.             modified := true;
  155.          until
  156.             not modified or else imin >= imax
  157.          loop
  158.             from
  159.                modified := false;
  160.                i := imax;
  161.                imin := imin + 1;
  162.             until
  163.                i < imin
  164.             loop
  165.                if c.item(i) > c.item(i - 1) then
  166.                   c.swap(i ,i - 1);
  167.                   modified := true;                  
  168.                end;
  169.                i := i - 1;
  170.             end;
  171.             if modified then
  172.                from
  173.                   modified := false;
  174.                   i := imin;
  175.                   imax := imax - 1;
  176.                until
  177.                   i > imax
  178.                loop
  179.                   if c.item(i + 1) > c.item(i) then
  180.                      c.swap(i ,i + 1);
  181.                      modified := true;                  
  182.                   end;
  183.                   i := i + 1;
  184.                end;
  185.             end;
  186.          end;
  187.       ensure
  188.          c.count = old c.count;
  189.          is_sorted(c)
  190.       end;
  191.    
  192.       heap_sort(c: COLLECTION[X]) is
  193.          -- Sort `c' using the heap sort algorithm.
  194.       require
  195.          c /= Void
  196.       local
  197.          i, c_lower, c_upper: INTEGER;
  198.       do
  199.          c_lower := c.lower;
  200.          c_upper := c.upper;
  201.          if c_upper > c_lower then
  202.             from
  203.                -- Build the very first heap first :
  204.                from
  205.                   i := c_lower + c.count // 2 + 1;
  206.                until
  207.                   i < c_lower
  208.                loop
  209.                   heap_repair(c,c_lower,i,c_upper);
  210.                   i := i - 1;
  211.                end;
  212.                --
  213.                i := c_upper;
  214.             until
  215.                i < c_lower + 1
  216.             loop
  217.                c.swap(c_lower,i);
  218.                heap_repair(c,c_lower,c_lower,i - 1);
  219.                i := i - 1;
  220.             end;
  221.          end;
  222.       ensure
  223.          c.count = old c.count;
  224.          is_sorted(c)
  225.       end;
  226.    
  227.  feature {NONE}  
  228.    
  229.       heap_repair(c: COLLECTION[X]; c_lower, first, last: INTEGER) is
  230.          -- Repair the heap from the node number `first' 
  231.          -- It considers that the last item of c is number `last'
  232.          -- It supposes that children are heaps.
  233.       require
  234.          c /= Void;
  235.          c.lower = c_lower;
  236.          c_lower <= first;
  237.          last <= c.upper
  238.       local
  239.          left_idx, right_idx: INTEGER;
  240.       do
  241.          left_idx := 1 - c_lower + 2 * first;
  242.          if left_idx <= last then -- not a leaf :
  243.             right_idx := 2 - c_lower + 2 * first;
  244.             if left_idx = last then
  245.                if c.item(first) > c.item(left_idx) then
  246.                   c.swap(first,left_idx);
  247.                end;
  248.             elseif c.item(first) < c.item(left_idx) then
  249.                if c.item(first) > c.item(right_idx) then
  250.                   c.swap(first,right_idx);                  
  251.                   heap_repair(c,c_lower,right_idx,last);
  252.                end;
  253.             elseif c.item(left_idx) < c.item(right_idx) then
  254.                c.swap(first,left_idx);
  255.                heap_repair(c,c_lower,left_idx,last);
  256.             else
  257.                c.swap(first,right_idx);
  258.                heap_repair(c,c_lower,right_idx,last);
  259.             end;
  260.          end;
  261.       end;
  262.    
  263.    
  264. feature {NONE}   
  265.    
  266.    von_neuman_line(src, dest: COLLECTION[X]; count, d_count, lower, imax: INTEGER) is
  267.       require
  268.          src /= dest;
  269.          src.lower = dest.lower;
  270.          src.upper = dest.upper;
  271.          count >= 1;
  272.          d_count = count * 2;
  273.          lower = src.lower;
  274.          imax = src.upper + 1
  275.       local
  276.          sg1: INTEGER;
  277.       do
  278.          from
  279.             sg1 := lower;
  280.          until
  281.             sg1 >= imax 
  282.          loop
  283.             von_neuman_inner_sort(src,dest,sg1,count,imax);
  284.             sg1 := sg1 + d_count;
  285.          end;
  286.       ensure
  287.          d_count >= dest.count implies is_sorted(dest)
  288.       end;
  289.  
  290.    von_neuman_inner_sort(src, dest: COLLECTION[X]; sg1, count, imax: INTEGER) is
  291.       require
  292.          src.valid_index(sg1)
  293.       local
  294.          i1, i2, i, i1max, i2max: INTEGER;
  295.       do
  296.          from
  297.             i1 := sg1;
  298.             i2 := sg1 + count;
  299.             i1max := i2.min(imax);
  300.             i2max := (i2 + count).min(imax);
  301.             i := i1;
  302.          until
  303.             i1 >= i1max or else i2 >= i2max
  304.          loop
  305.             if not(src.item(i1) <= src.item(i2)) then
  306.                dest.put(src.item(i1),i);
  307.                i1 := i1 + 1;
  308.             else
  309.                dest.put(src.item(i2),i);
  310.                i2 := i2 + 1;
  311.             end;
  312.             i := i + 1;
  313.          end;
  314.          if i1 >= i1max then
  315.             from until i2 >= i2max
  316.             loop
  317.                dest.put(src.item(i2),i);
  318.                i2 := i2 + 1; i := i + 1;
  319.             end;
  320.          else
  321.             from until i1 >= i1max
  322.             loop
  323.                dest.put(src.item(i1),i);
  324.                i1 := i1 + 1; i := i + 1;
  325.             end;
  326.          end;
  327.       end;
  328.    
  329.    quick_sort_region(c: COLLECTION[X]; gauche,droite:INTEGER) is
  330.       local
  331.          pivot : INTEGER
  332.          i : INTEGER
  333.       do
  334.          if gauche < droite then
  335.             i := gauche + (droite-gauche) // 2 + 1;
  336.             c.swap(gauche,i);
  337.             pivot := gauche;
  338.             from
  339.                i := gauche +1
  340.             until
  341.                i > droite
  342.             loop
  343.                if c.item(i) >= c.item(gauche) then
  344.                   pivot := pivot + 1;
  345.                   c.swap(pivot,i);
  346.                end;
  347.                i := i + 1;
  348.             end;
  349.             c.swap(gauche,pivot);
  350.             quick_sort_region(c , gauche , pivot - 1);
  351.             quick_sort_region(c , pivot + 1 , droite);
  352.          end;
  353.       end;
  354.    
  355. end -- REVERSE_COLLECTION_SORTER
  356.