Sorting algorithms/Shell sort

From Rosetta Code
Revision as of 20:04, 29 May 2008 by rosettacode>Mwn3d (Clarity, grammar)
Task
Sorting algorithms/Shell sort
You are encouraged to solve this task according to the task description, using any language you may know.

In this task, the goal is to sort an array of elements using the Shell sort algorithm, a diminishing increment sort. The Shell sort is named after its inventor, Donald Shell, who published the algorithm in 1959. Shellsort is a sequence of interleaved insertion sorts based on an increment sequence. The increment size is reduced after each pass until the increment size is 1. With an increment size of 1, the sort is a basic insertion sort, but by this time the data is guaranteed to be almost sorted, which is insertion sort's "best case". Any sequence will sort the data as long as it ends in 1, but some work better than others. Empirical studies have shown a geometric increment sequence with a ratio of about 2.2 work well in practice. [1]

Ada

This is a generic implementation of the shell sort. Ada allows arrays to be indexed by integer or enumeration types starting at any value. This version deals with any kind or value of valid index type. <ada> generic

  type Element_Type is digits <>;
  type Index_Type is (<>);
  type Array_Type is array(Index_Type range <>) of Element_Type;

package Shell_Sort is

  procedure Sort(Item : in out Array_Type);

end Shell_Sort; </ada> <ada>package body Shell_Sort is

  ----------
  -- Sort --
  ----------
  procedure Sort (Item : in out Array_Type) is
     Increment : Natural := Index_Type'Pos(Item'Last) / 2;
     J : Index_Type;
     Temp : Element_Type;
  begin
     while Increment > 0 loop
        for I in Index_Type'Val(Increment) .. Item'Last loop
           J := I;
           Temp := Item(I);
           while J > Index_Type'val(Increment) and then Item (Index_Type'Val(Index_Type'Pos(J) - Increment)) > Temp loop
              Item(J) := Item (Index_Type'Val(Index_Type'Pos(J) - Increment));
              J := Index_Type'Val(Index_Type'Pos(J) - Increment);
           end loop;
           Item(J) := Temp;
        end loop;
        if Increment = 2 then
           Increment := 1;
        else
           Increment := Increment * 5 / 11;
        end if;
     end loop;
  end Sort;

end Shell_Sort; </ada>

C

This implementation uses an array of pre-defined increments

#include <ansi_c.h>

#define ARRAYSIZE 100000 /* or whatever */

void shellsort (int a[], int length);

int main (int argc, char *argv[])
{
  int intArray[ARRAYSIZE], i, increment; 
 
  for(i=0; i<=ARRAYSIZE-1; i++)
   intArray[i] = rand();
   shellsort(intArray, ARRAYSIZE);
}  

void shellsort (int a[], int length)
{
  int i, j, k, temp, increment;
  int incSequence[] = {412771, 165103, 66041, 26417, 10567, 4231, 1693, 673, 269, 107, 43, 17, 7, 3, 1};

  for (k = 0; k <= 14; k++)
  {
    if (incSequence[k]*2 > length) continue;
    increment = incSequence[k];   
    for (i=0; i < length; i++)
    {
      temp = a[i];
      for (j = i - increment; j >= 0; j -= increment)
      {
        if (a[j] <= temp) break;
        a[j + increment] = a[j];
      }
      a[j + increment] = temp;
    }
  }	  
}


Fortran

MODULE sort

CONTAINS

SUBROUTINE Shell_Sort(a)

  IMPLICIT NONE
  INTEGER :: i, j, increment
  REAL :: temp
  REAL, INTENT(in out) :: a(:)
	
  increment = SIZE(a) / 2
  DO WHILE (increment > 0)
      DO i = increment+1, SIZE(a)
         j = i
         temp = a(i)
         DO WHILE (j >= increment+1 .AND. a(j-increment) > temp)
            a(j) = a(j-increment)
            j = j - increment
         END DO
         a(j) = temp
      END DO
      IF (increment == 2) THEN
   	  increment = 1
      ELSE
         increment = increment * 5 / 11
      END IF      
  END DO
 
END SUBROUTINE Shell_Sort

END MODULE sort

PROGRAM Shellsort

USE sort

  IMPLICIT NONE
  REAL :: array(1000)
     
  CALL RANDOM_SEED
  CALL RANDOM_NUMBER(array)
 
  WRITE (*,*) "Unsorted array"
  WRITE (*,*) array
  WRITE (*,*) 
  CALL Shell_Sort(array)
  WRITE (*,*) "Sorted array"
  WRITE (*,*) array
  
END PROGRAM Shellsort

Java

Translation of: Fortran

This method will sort in place. If you want to preserve your unsorted array, use a copy of the array as an argument to this method. <java>public static void shell(int[] a) { int increment = a.length / 2; while (increment > 0) { for (int i = increment; i < a.length; i++) { int j = i; int temp = a[i]; while (j >= increment && a[j - increment] > temp) { a[j] = a[j - increment]; j -= increment; } a[j] = temp; } if (increment == 2) { increment = 1; } else { increment *= (5.0 / 11); } } }</java>