home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 3 / AACD03.BIN / AACD / Programming / sofa / archive / SmallEiffel.lha / SmallEiffel / lib_std / collection_sorter.e < prev    next >
Text File  |  1999-06-05  |  10KB  |  353 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 COLLECTION_SORTER[X -> COMPARABLE]
  13. --
  14. -- Some algorithms to sort any COLLECTION[COMPARABLE].
  15. --
  16. -- Elements are sorted using increasing order: small elements 
  17. -- at the begining of the colection, large at the end (decreasing
  18. -- order is implemented by class REVERSE_COLLECTION_SORTER).
  19. -- 
  20. -- 
  21. -- How to use this expanded class :
  22. --
  23. --          local
  24. --             sorter: COLLECTION_SORTER[INTEGER];
  25. --             array: ARRAY[INTEGER];
  26. --          do
  27. --             array := <<1,3,2>>;
  28. --             sorter.sort(array);
  29. --             check
  30. --                sorter.is_sorted(array);
  31. --             end;
  32. --             ...
  33. --
  34.  
  35. feature
  36.  
  37.    is_sorted(c: COLLECTION[X]): BOOLEAN is
  38.          -- Is `c' already sorted ?
  39.          -- Uses infix "<=" for comparison.
  40.       require
  41.          c /= Void
  42.       local
  43.          i, c_upper: INTEGER;
  44.          elt1, elt2: X;
  45.       do
  46.          i := c.lower;
  47.          c_upper := c.upper;
  48.          Result := true;
  49.          if c_upper > i then
  50.             from
  51.                elt1 := c.item(i);
  52.             invariant
  53.                c.valid_index(i)
  54.             until
  55.                not Result or else i >= c_upper
  56.             loop
  57.                i := i + 1;
  58.                elt2 := c.item(i);
  59.                Result := elt1 <= elt2;
  60.                elt1 := elt2;
  61.             end;
  62.          end;
  63.       ensure
  64.          c.is_equal(old c.twin)
  65.       end;
  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.    heap_sort(c: COLLECTION[X]) is
  143.          -- Sort `c' using the heap sort algorithm.
  144.       require
  145.          c /= Void
  146.       local
  147.          i, c_lower, c_upper: INTEGER;
  148.       do
  149.          c_lower := c.lower;
  150.          c_upper := c.upper;
  151.          if c_upper > c_lower then
  152.             from
  153.                -- Build the very first heap first :
  154.                from
  155.                   i := c_lower + c.count // 2 + 1;
  156.                until
  157.                   i < c_lower
  158.                loop
  159.                   heap_repair(c,c_lower,i,c_upper);
  160.                   i := i - 1;
  161.                end;
  162.                --
  163.                i := c_upper;
  164.             until
  165.                i < c_lower + 1
  166.             loop
  167.                c.swap(c_lower,i);
  168.                heap_repair(c,c_lower,c_lower,i - 1);
  169.                i := i - 1;
  170.             end;
  171.          end;
  172.       ensure
  173.          c.count = old c.count;
  174.          is_sorted(c)
  175.       end;
  176.    
  177.    bubble_sort(c: COLLECTION[X]) is
  178.          -- Sort `c' using the bubble sort algorithm.
  179.          -- Uses infix "<" for comparison.
  180.       require
  181.          c /= Void
  182.       local
  183.          i, imax, imin: INTEGER;
  184.          modified: BOOLEAN;
  185.       do
  186.          from
  187.             imax := c.upper;
  188.             imin := c.lower;
  189.             modified := true;
  190.          until
  191.             not modified or else imin >= imax
  192.          loop
  193.             from
  194.                modified := false;
  195.                i := imax;
  196.                imin := imin + 1;
  197.             until
  198.                i < imin
  199.             loop
  200.                if c.item(i) < c.item(i - 1) then
  201.                   c.swap(i ,i - 1);
  202.                   modified := true;                  
  203.                end;
  204.                i := i - 1;
  205.             end;
  206.             if modified then
  207.                from
  208.                   modified := false;
  209.                   i := imin;
  210.                   imax := imax - 1;
  211.                until
  212.                   i > imax
  213.                loop
  214.                   if c.item(i + 1) < c.item(i) then
  215.                      c.swap(i ,i + 1);
  216.                      modified := true;                  
  217.                   end;
  218.                   i := i + 1;
  219.                end;
  220.             end;
  221.          end;
  222.       ensure
  223.          c.count = old c.count;
  224.          is_sorted(c)
  225.       end;
  226.    
  227. feature {NONE}   
  228.    
  229.    von_neuman_line(src, dest: COLLECTION[X]; count, d_count, lower, imax: INTEGER) is
  230.       require
  231.          src /= dest;
  232.          src.lower = dest.lower;
  233.          src.upper = dest.upper;
  234.          count >= 1;
  235.          d_count = count * 2;
  236.          lower = src.lower;
  237.          imax = src.upper + 1
  238.       local
  239.          sg1: INTEGER;
  240.       do
  241.          from
  242.             sg1 := lower;
  243.          until
  244.             sg1 >= imax 
  245.          loop
  246.             von_neuman_inner_sort(src,dest,sg1,count,imax);
  247.             sg1 := sg1 + d_count;
  248.          end;
  249.       ensure
  250.          d_count >= dest.count implies is_sorted(dest)
  251.       end;
  252.  
  253.    von_neuman_inner_sort(src, dest: COLLECTION[X]; sg1, count, imax: INTEGER) is
  254.       require
  255.          src.valid_index(sg1)
  256.       local
  257.          i1, i2, i, i1max, i2max: INTEGER;
  258.       do
  259.          from
  260.             i1 := sg1;
  261.             i2 := sg1 + count;
  262.             i1max := i2.min(imax);
  263.             i2max := (i2 + count).min(imax);
  264.             i := i1;
  265.          until
  266.             i1 >= i1max or else i2 >= i2max
  267.          loop
  268.             if src.item(i1) <= src.item(i2) then
  269.                dest.put(src.item(i1),i);
  270.                i1 := i1 + 1;
  271.             else
  272.                dest.put(src.item(i2),i);
  273.                i2 := i2 + 1;
  274.             end;
  275.             i := i + 1;
  276.          end;
  277.          if i1 >= i1max then
  278.             from until i2 >= i2max
  279.             loop
  280.                dest.put(src.item(i2),i);
  281.                i2 := i2 + 1; i := i + 1;
  282.             end;
  283.          else
  284.             from until i1 >= i1max
  285.             loop
  286.                dest.put(src.item(i1),i);
  287.                i1 := i1 + 1; i := i + 1;
  288.             end;
  289.          end;
  290.       end;
  291.  
  292.    heap_repair(c: COLLECTION[X]; c_lower, first, last: INTEGER) is
  293.          -- Repair the heap from the node number `first' 
  294.          -- It considers that the last item of c is number `last'
  295.          -- It supposes that children are heaps.
  296.       require
  297.          c /= Void;
  298.          c.lower = c_lower;
  299.          c_lower <= first;
  300.          last <= c.upper
  301.       local
  302.          left_idx, right_idx: INTEGER;
  303.       do
  304.          left_idx := 1 - c_lower + 2 * first;
  305.          if left_idx <= last then -- not a leaf :
  306.             right_idx := 2 - c_lower + 2 * first;
  307.             if left_idx = last then
  308.                if c.item(first) < c.item(left_idx) then
  309.                   c.swap(first,left_idx);
  310.                end;
  311.             elseif c.item(first) > c.item(left_idx) then
  312.                if c.item(first) < c.item(right_idx) then
  313.                   c.swap(first,right_idx);                  
  314.                   heap_repair(c,c_lower,right_idx,last);
  315.                end;
  316.             elseif c.item(left_idx) > c.item(right_idx) then
  317.                c.swap(first,left_idx);
  318.                heap_repair(c,c_lower,left_idx,last);
  319.             else
  320.                c.swap(first,right_idx);
  321.                heap_repair(c,c_lower,right_idx,last);
  322.             end;
  323.          end;
  324.       end;
  325.    
  326.    quick_sort_region(c: COLLECTION[X]; gauche,droite:INTEGER) is
  327.       local
  328.          pivot : INTEGER
  329.          i : INTEGER
  330.       do
  331.          if gauche<droite then
  332.             i := gauche + (droite-gauche) // 2 + 1;
  333.             c.swap(gauche,i);
  334.             pivot := gauche;
  335.             from
  336.                i := gauche +1
  337.             until
  338.                i > droite
  339.             loop
  340.                if c.item(i) < c.item(gauche) then
  341.                   pivot := pivot + 1;
  342.                   c.swap(pivot,i);
  343.                end;
  344.                i := i + 1;
  345.             end;
  346.             c.swap(gauche,pivot);
  347.             quick_sort_region(c , gauche , pivot - 1);
  348.             quick_sort_region(c , pivot + 1 , droite);
  349.          end;
  350.       end;
  351.    
  352. end -- COLLECTION_SORTER
  353.