Skip to content

Shellsort PHP implementation

2012 June 19
tags:
by Richard Knop

Continuing my challenge, after implementing Bubble sort, Selection sort and Insertion sort, here comes Shellsort. Named after Donald Shell, it is basically a generalisation of simpler algorithms like Bubble sort or Insertion sort. It starts with far apart elements. The gap between elements is then decreased after every iteration.

That means we start with small subarrays and then with every iteration the subarrays are getting bigger as we are decreasing the gap between elements. I chose to start with a gap equal to half of the array length rounded down. After every iteration I divide the gap by two and round down again until zero is reached.

Example:

  1. <?php
  2.  
  3. $arr = array();
  4. for ($i = 0; $i < 100; ++$i) {
  5.     $arr[] = $i;
  6. }
  7. shuffle($arr);
  8. $sortedArr = shellSort($arr);
  9. var_dump($sortedArr);
  10.  
  11. function shellSort(array $arr) {
  12.     $gap = floor(count($arr)/2);
  13.     while ($gap > 0) {
  14.         for ($i = 0; $i < count($arr)-$gap; ++$i) {
  15.             $arrWithGapsKeys = array();
  16.             $arrWithGaps = array();
  17.             $loop = true;
  18.             $j = $i;
  19.             while ($loop) {
  20.                 if (isset($arr[$j])) {
  21.                     $arrWithGapsKeys[] = (int)$j;
  22.                     $arrWithGaps[] = $arr[$j];
  23.                     $j += $gap;
  24.                 } else {
  25.                     $loop = false;
  26.                 }
  27.             }
  28.             $arrWithGapsOrdered = insertionSort($arrWithGaps);
  29.             foreach ($arrWithGapsKeys as $key) {
  30.                 $arr[$key] = current($arrWithGapsOrdered);
  31.                 next($arrWithGapsOrdered);
  32.             }
  33.         }
  34.         $gap = floor($gap/2);
  35.     }
  36.     return $arr;
  37. }
  38.  
  39. function insertionSort(array $table) {
  40.     $leftHand = array();
  41.     foreach ($table as $card) {
  42.         if (0 === count($leftHand)) {
  43.             $leftHand[] = $card;
  44.         } else {
  45.             $insertedCard = false;
  46.             $reindexedLeftHand = array();
  47.             for ($i = count($leftHand)-1; $i >= 0; $i) {
  48.                 if ($card >= $leftHand[$i]) {
  49.                     for ($j = 0; $j <= $i; ++$j) {
  50.                         $reindexedLeftHand[$j] = $leftHand[$j];
  51.                     }
  52.                     $reindexedLeftHand[] = $card;
  53.                     for ($j = $i+1; $j < count($leftHand); ++$j) {
  54.                         $reindexedLeftHand[$j+1] = $leftHand[$j];
  55.                     }
  56.                     $insertedCard = true;
  57.                     break;
  58.                 }
  59.             }
  60.             if (false === $insertedCard) {
  61.                 $reindexedLeftHand[] = $card;
  62.                 foreach ($leftHand as $cardInLeftHand) {
  63.                     $reindexedLeftHand[] = $cardInLeftHand;
  64.                 }
  65.             }
  66.             $leftHand = $reindexedLeftHand;
  67.         }
  68.     }
  69.     return $leftHand;
  70. }

Will result in:

array(100) {
  [0]=>
  int(0)
  [1]=>
  int(1)
  [2]=>
  int(2)
  [3]=>
  int(3)
  [4]=>
  int(4)
  [5]=>
  int(5)
  [6]=>
  int(6)
  [7]=>
  int(7)
  [8]=>
  int(8)
  [9]=>
  int(9)
  [10]=>
  int(10)
  [11]=>
  int(11)
  [12]=>
  int(12)
  [13]=>
  int(13)
  [14]=>
  int(14)
  [15]=>
  int(15)
  [16]=>
  int(16)
  [17]=>
  int(17)
  [18]=>
  int(18)
  [19]=>
  int(19)
  [20]=>
  int(20)
  [21]=>
  int(21)
  [22]=>
  int(22)
  [23]=>
  int(23)
  [24]=>
  int(24)
  [25]=>
  int(25)
  [26]=>
  int(26)
  [27]=>
  int(27)
  [28]=>
  int(28)
  [29]=>
  int(29)
  [30]=>
  int(30)
  [31]=>
  int(31)
  [32]=>
  int(32)
  [33]=>
  int(33)
  [34]=>
  int(34)
  [35]=>
  int(35)
  [36]=>
  int(36)
  [37]=>
  int(37)
  [38]=>
  int(38)
  [39]=>
  int(39)
  [40]=>
  int(40)
  [41]=>
  int(41)
  [42]=>
  int(42)
  [43]=>
  int(43)
  [44]=>
  int(44)
  [45]=>
  int(45)
  [46]=>
  int(46)
  [47]=>
  int(47)
  [48]=>
  int(48)
  [49]=>
  int(49)
  [50]=>
  int(50)
  [51]=>
  int(51)
  [52]=>
  int(52)
  [53]=>
  int(53)
  [54]=>
  int(54)
  [55]=>
  int(55)
  [56]=>
  int(56)
  [57]=>
  int(57)
  [58]=>
  int(58)
  [59]=>
  int(59)
  [60]=>
  int(60)
  [61]=>
  int(61)
  [62]=>
  int(62)
  [63]=>
  int(63)
  [64]=>
  int(64)
  [65]=>
  int(65)
  [66]=>
  int(66)
  [67]=>
  int(67)
  [68]=>
  int(68)
  [69]=>
  int(69)
  [70]=>
  int(70)
  [71]=>
  int(71)
  [72]=>
  int(72)
  [73]=>
  int(73)
  [74]=>
  int(74)
  [75]=>
  int(75)
  [76]=>
  int(76)
  [77]=>
  int(77)
  [78]=>
  int(78)
  [79]=>
  int(79)
  [80]=>
  int(80)
  [81]=>
  int(81)
  [82]=>
  int(82)
  [83]=>
  int(83)
  [84]=>
  int(84)
  [85]=>
  int(85)
  [86]=>
  int(86)
  [87]=>
  int(87)
  [88]=>
  int(88)
  [89]=>
  int(89)
  [90]=>
  int(90)
  [91]=>
  int(91)
  [92]=>
  int(92)
  [93]=>
  int(93)
  [94]=>
  int(94)
  [95]=>
  int(95)
  [96]=>
  int(96)
  [97]=>
  int(97)
  [98]=>
  int(98)
  [99]=>
  int(99)
}
2 Responses leave one →
  1. October 30, 2012

    It is usually a generalisation of simpler algorithms like Bubble sort or Insertion sort. It starts with far apart elements. The gap between elements is then decreased after every edition.

Trackbacks and Pingbacks

  1. Merge sort PHP implementation | Zend Framework Blog

Leave a Reply

Note: You can use basic XHTML in your comments. Your email address will never be published.

Subscribe to this comment feed via RSS