Hill sorting exchange sorting
● Problem introduction:
In insertion sort, if the arrangement of the array elements is relatively optimistic , then the number of insertions will be relatively small, and the efficiency will be very high. However, many times, the data is so disrespectful, such as the following array to be sorted: [2,3,4, 5,6,7,1], this array, if insertion sort is used, will look like the following:
1. First round: [2,3,4,5,6,7, 7]
2. Second round:[2,3,4,5,6,6,7]
3. Third round:[2,3,4,5, 5,6,7]
4. The fourth round:[2,3,4,4,5,6,7]
5. The fifth round:[2,3, 3,4,5,6,7]
6. The sixth round:[2,2,3,4,5,6,7]
7. The seventh round:[ 1,2,3,4,5,6,7]
This is the least optimistic situation and a waste of time. Therefore, some experts later studied it, optimized it, and invented the hope. Sort it.
Hill sort (Shell's Sort) is a kind of insertion sort, also known as "Diminishing Increment Sort" (Diminishing Increment Sort). It is a more efficient and improved version of the direct insertion sort algorithm.
Hill sorting is a non-stable sorting algorithm. This method is named after D.L.Shell proposed it in 1959.
Hill sorting is to group records by a certain increment of the subscript, and use the direct insertion sorting algorithm to sort each group; as the increment gradually decreases, each group contains more and more keywords. When the amount is reduced to 1,
The entire file is divided into one group, and the algorithm terminates
●
Array example description:1. For example, there are An array to be sorted [9,6,1,3,0,5.7,2,8,4]
2. The above array has a total of 10 elements. It divides the array into 10 for the first time. /2 = 5 groups, then compare them in pairs, exchange the size and position: as follows:
<?php $arr = [9,6,1,3,0, 5,7,2,8,4]; $arr[0] > $arr[5] ? '交换位置,小数交换在前,大数交换在后' : '不交换位置'; $arr[1] > $arr[6] ? '交换位置,小数交换在前,大数交换在后' : '不交换位置'; $arr[2] > $arr[7] ? '交换位置,小数交换在前,大数交换在后' : '不交换位置'; $arr[3] > $arr[8] ? '交换位置,小数交换在前,大数交换在后' : '不交换位置'; $arr[4] > $arr[9] ? '交换位置,小数交换在前,大数交换在后' : '不交换位置'; for ($i = 5; $i < 10; $i++) { for ($j = $i - 5; $j >= 0; $j-=5) { if ($data[$j] > $data[$j+5]) { $temp = $data[$j]; $data[$j] = $data[$j+5]; $data[$j+5] = $temp; } } }
The final result obtained in the first round is: [5,6,1,3,0,9,7,2, 8,4]
3. The second round of comparison begins again. The second round is based on the previous first round and is divided into 5/2 = 2 groups again. Then the positions are exchanged in pairs, and the big and small fingers are Exchange: as follows:
<?php $arr = [5,6,1,3,0,9,7,2,8,4]; $arr[0] > $arr[2];//1,5 [1,6,5,3,0,9,7,2,8,4] $arr[2] > $arr[4];//0,5 [1,6,0,3,5,9,7,2,8,4] $arr[4] > $arr[6];//5,7 [1,6,0,3,5,9,7,2,8,4] $arr[6] > $arr[8];//7,8 [1,6,0,3,5,9,7,2,8,4] $arr[1] > $arr[3];//3,6 [1,3,0,6,5,9,7,2,8,4] $arr[3] > $arr[5];//6,9 [1,3,0,6,5,9,7,2,8,4] $arr[5] > $arr[7];//2,9 [1,3,0,6,5,2,7,9,8,4] $arr[7] > $arr[9];//4,9 [1,3,0,6,5,2,7,4,8,9] ... for ($i = 2; $i < 10; $i++) { for ($j = $i - 2; $j >= 0; $j-=2) { if ($data[$j] > $data[$j+2]) { $temp = $data[$j]; $data[$j] = $data[$j+2]; $data[$j+2] = $temp; } } }
The final result is: [0,2,1,3,6,4,7,6,8,9]
4. Finally group again Compare: 2/2 = 1 group. That is, in the end, each two is compared, and then the positions are swapped again
<?php $arr = [0,2,1,3,5,4,7,6,8,9]; $arr[0] > $arr[1];//[1,3,0,6,5,2,7,4,8,9] $arr[1] > $arr[2];//[1,0,3,6,5,2,7,4,8,9] $arr[2] > $arr[3];//[1,0,3,6,5,2,7,4,8,9] $arr[3] > $arr[4];//[1,0,3,5,6,2,7,4,8,9] $arr[4] > $arr[5];//[1,0,3,5,2,6,7,4,8,9] $arr[5] > $arr[6];//[1,0,3,5,2,6,7,4,8,9] $arr[6] > $arr[7];//[1,0,3,5,2,6,4,7,8,9] $arr[7] > $arr[8];//[1,0,3,5,2,6,4,7,8,9] $arr[8] > $arr[9];//[1,0,3,5,2,6,4,7,8,9] ... for ($i = 1; $i < 10; $i++) { for ($j = $i - 1; $j >= 0; $j-=1) { if ($data[$j] > $data[$j+1]) { $temp = $data[$j]; $data[$j] = $data[$j+1]; $data[$j+1] = $temp; } } }
Finally, the result is obtained: [0,1,2,3,4,5,6,7,8,9]
●
The complete code is as follows:The above is the detailed content of PHP sorting algorithm Hill sorting. For more information, please follow other related articles on the PHP Chinese website!<?php
class ShellSort
{
/*** Notes: 希尔排序之交换法排序
* User: LiYi\ * Date: 2019/11/12 0012\ * Time: 14:30\ * @param array $data\ * @return array\ */\
public static function shellSortArray(array $data):array
{
if (!is_array($data)) {
return ['message' => '必须传入数组比较排序'];
}
$count = count($data);//得到数组的个数
//如果数组的个数小于等于1就直接返回
if ($count <= 1) {return $data;}
//$gap 是每次减半的分组,直到只可以分为一组结束,在php里面需要注意,两个整数相除,除不尽的情况下,得到的是一个浮点数,不是一个向下
//取整的的整数,所以在最后判断gap 退出循环的时候,需要判断它 >= 1
for ($gap = $count / 2; $gap >= 1; $gap /= 2) {
for ($i = $gap; $i < $count; $i++) {
for ($j = $i - $gap; $j >= 0; $j-=$gap) {
if ($data[$j] > $data[$j+$gap]) {
//这个地方是比较第一个数和它的步长做比较,交换也是一样
$temp = $data[$j];
$data[$j] = $data[$j+$gap];
$data[$j+$gap] = $temp;
}
}
}
}
return $data;
}
public static function validate(array $data)
{
if (!is_array($data)) {
return ['message' => '必须传入数组比较排序'];
}
$count = count($data);//得到数组的个数
//如果数组的个数小于等于1就直接返回
if ($count <= 1){
return $data;
}
return [$data, $count];
}
/**\ * Notes: 希尔排序之移位法排序
* User: LiYi
* Date: 2019/11/12 0012
* Time: 14:29
* @param array $data
* @return array*/
public static function ShellSortMoveArray(array $data)
{
$count = count($data);//得到数组总数
for ($gap = $count / 2; $gap > 0; $gap /= 2) {
//缩小增量,每次减半
$gap = floor($gap);
for ($i = $gap; $i < $count; $i++) {
// $insertIndex = $i;//待插入元素的下表
$insertValue = $data[$insertIndex];//待插入元素的值
echo "insertIndex=$insertIndex" . PHP_EOL;
echo "insertValue=$insertValue" . PHP_EOL;
if ($data[$insertIndex] < $data[$insertIndex - $gap]) {
//判断待插入元素和它步长的元素比较,待插入元素小就进入循环
//判断是否越界了,第一个元素的下标是要大于等于0的,否则退出循环
//判断后面的元素比前面的元素小,进入循环,否则退出循环
while ($insertIndex - $gap >= 0 && $insertValue < $data[$insertIndex - $gap]) {
//把步长前面的大的值向后移动
$data[$insertIndex] = $data[$insertIndex - $gap];
$insertIndex -= $gap;//每循环一次就把带插入的坐标减去补偿\
} //把带插的小值插入到前面
$data[$insertIndex] = $insertValue;
}
}
}
return $data;
}
public static function testShellOne(array $data)
{
$temp = 0;
$count = count($data);
for ($i = 5; $i < $count; $i++) {
for ($j = $i - 5; $j >= 0; $j-=5) {
if ($data[$j] > $data[$j+5]) {
$temp = $data[$j];
$data[$j] = $data[$j+5];
$data[$j+5] = $temp;
}
}
}
for ($i = 2; $i < $count; $i++) {
for ($j = $i - 2; $j >= 0; $j-=2) {
if ($data[$j] > $data[$j+2]) {
$temp = $data[$j];
$data[$j] = $data[$j+2];
$data[$j+2] = $temp;
}
}
}
for ($i = 1; $i < 10; $i++) {
for ($j = $i - 1; $j >= 0; $j-=1) {
if ($data[$j] > $data[$j+1]) {
$temp = $data[$j];
$data[$j] = $data[$j+1];
$data[$j+1] = $temp;
}
}
}
var_dump($data);
}
}
var_dump(ShellSort::shellSortMoveArray([0 => 9, 1 => 6, 2 => 1, 3 => 3, 4 => 0, 5 => 5, 6 => 7, 7 => 2, 8 => 8, 9 => 4]));
// $gap = 10 / 2 = 5
// $insertIndex = $i = $gap = 5
// $insertValue = $data[$insertIndex] = $data[5] = 5;
// $data[$insertIndex] < $data[$insertIndex - $gap] == $data[5] < $data[5-5] = $data[0] ==> 5 < 9
// while(5 - 5 >= 0 && 5 < 9) {
// $data[5] = $data[5-5] = $data[0] = 9
// $insertIndex -= 5 = 0;
//}
// $data[$insertIndex] = $data[0] = $insertValue = 5
// $i++ = 6;
// $insertIndex = $i = 6
// $insertValue = $data[$insertIndex] = $data[6] = 7;
// $data[$insertIndex] < $data[$insertIndex - $gap] == $data[6] < $data[6-5] = $data[1] ==> 7 < 6
// $i++ = 7;
// $insertIndex = $i = 7
// $insertValue = $data[$insertIndex] = $data[7] = 2;
// $data[$insertIndex] < $data[$insertIndex - $gap] == $data[7] < $data[7-5] = $data[2] ==> 2 < 1
// $i++ = 8;
// $insertIndex = $i = 8
// $insertValue = $data[$insertIndex] = $data[8] = 8;
// $data[$insertIndex] < $data[$insertIndex - $gap] == $data[8] < $data[8-5] = $data[3] ==> 8 < 3
// $i++ = 9;
// $insertIndex = $i = 9
// $insertValue = $data[$insertIndex] = $data[9] = 4;
// $data[$insertIndex] < $data[$insertIndex - $gap] == $data[9] < $data[9-5] = $data[4] ==> 4 < 0