#** 八大排序算法**
排序分为内排序和外排序
- 内排序指的是内部排序,即数据记录在内存中进行排序。
- 外排序一般是指的不能一次容纳的全部排序记录,需要访问外存的排序。
内部排序主要分为五类,八种。
- 插入排序
- 直接插入排序
- 希尔插入排序
- 选择排序
- 简单选择排序
- 堆排序
- 交换排序
- 冒泡拍寻
- 快速选择排序
- 归并排序
- 基数排序
当n比较大时应当采用归并排序,堆排序,快速选择排序,时间复杂度为O(nlog2n)的排序方式。 其中快速排序是目前内部排序中最好的方法,但待排序为随机分布时,快速选择排序用时最短。
插入排序
###直接插入排序(StraightInsertionSort)
<?php
/*返回当前Unix时间戳及微秒数*/
function getCurrentTime () {
list ($msec, $sec) = explode(" ", microtime());
return (float)$msec + (float)$sec;
}
/*生成制定长度的随机数组*/
function ArrayRank(int $length):array{
for($i=0;$i<$length;$i++){
$arr[]=rand(0,100);
}
return $arr;
}
/*直接插入排序*/
function StraightInsertionSort(array $arr):array{
for($i=1;$i<sizeof($arr);$i++){
if($arr[$i]<$arr[$i-1]){
$key=$i-1; //获取空位点
$item=$arr[$i];
$arr[$i]=$arr[$i-1];
while($key!=0&&$item<$arr[$key-1]){
$arr[$key]=$arr[$key-1];
$key--;
}
$arr[$key]=$item;
}
}
return $arr;
}
$begin = getCurrentTime();
$arr=ArrayRank(100);
print_r($arr);
echo "<br/>";
print_r(StraightInsertionSort($arr));
$end = getCurrentTime();
$spend = $end - $begin;
echo "脚本执行时间为:".$spend."\n"; ```
时间复杂度为O(n^2);
###希尔插入排序(ShellInsertionSort)
希尔排序是在简单排序的基础上增加了增量的概念,因此希尔排序又叫缩小增量排序
思路:先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序。
<?php /*返回当前Unix时间戳及微秒数*/ function getCurrentTime () { list ($msec, $sec) = explode(" ", microtime()); return (float)$msec + (float)$sec; } /*生成制定长度的随机数组*/ function ArrayRank(int $length):array{ for($i=0;$i<$length;$i++){ $arr[]=rand(0,100); } return $arr; } /*希尔排序 可以设置初始增量,增量的设定影响执行效率及排序结果 然后进行循环希尔插入排序 */ function ShellSort(array $arr,int $dk):array{ while ($dk>=1) { $arr=ShellInsertSort($arr,$dk); $dk--; } return $arr; } /*简单插入排序变形,对其进行增量的的排序 */ function ShellInsertSort(array $arr,int $dk):array{ for($i=$dk;$i<sizeof($arr);$i++){ if($arr[$i]<$arr[$i-$dk]){ $item=$arr[$i]; $key=$i-$dk; $arr[$i]=$arr[$i-$dk]; while($key-$dk>=0&&$item<$arr[$key-$dk]){ $arr[$key]=$arr[$key-$dk]; $key-=$dk; } $arr[$key]=$item; } } return $arr; } $begin = getCurrentTime(); $arr=ArrayRank(500); print_r($arr); echo "<br/>"; print_r(ShellSort($arr,sizeof($arr)/2)); $end = getCurrentTime(); $spend = $end - $begin; echo "脚本执行时间为:".$spend."\n"; ``` 希尔排序时效分析很难,关键码的比较次数与记录移动次数依赖于增量因子序列d的选取,特定情况下可以准确估算出关键码的比较次数和记录的移动次数。目前还没有人给出选取最好的增量因子序列的方法。增量因子序列可以有各种取法,有取奇数的,也有取质数的,但需要注意:增量因子中除1 外没有公因子,且最后一个增量因子必须为1。希尔排序方法是一个不稳定的排序方法。 ###简单插入排序(SimpleSelectionSort) 在要排序的一组数中,选出最小(或者最大)的一个数与第1个位置的数交换;然后在剩下的数当中再找最小(或者最大)的与第2个位置的数交换,依次类推,直到第n-1个元素(倒数第二个数)和第n个元素(最后一个数)比较为止。 ``` <?php /*返回当前Unix时间戳及微秒数*/ function getCurrentTime () { list ($msec, $sec) = explode(" ", microtime()); return (float)$msec + (float)$sec; } /*生成制定长度的随机数组*/ function ArrayRank(int $length):array{ for($i=0;$i<$length;$i++){ $arr[]=rand(0,100); } return $arr; } /*简单选择排序*/ function SimpleSelectionSort(array $arr):array{ $length=sizeof($arr); for($i=0;$i<$length;$i++){ $key=$i; for($j=$i;$j<$length;$j++){ if($arr[$key]>$arr[$j]){/*选择最小值*/ $key=$j; } } $item=$arr[$key]; $arr[$key]=$arr[$i]; $arr[$i]=$item; } return $arr; } /*二元选择排序,简单排序的改进 简单选择排序,每趟循环只能确定一个元素排序后的定位。 我们可以考虑改进为每趟循环确定两个元素(当前趟最大和最小记录)的位置,从而减少排序所需的循环次数。 改进后对n个数据进行排序,最多只需进行[n/2]趟循环即可。*/ function TwoElementSelectionSort(array $arr):array{ $length=sizeof($arr); for($i=0;$i<$length/2;$i++){ $max=$min=$i; for($j=$i;$j<$length;$j++){ if($arr[$min]>$arr[$j]){ $min=$j; } if($arr[$max]<$arr[$j]){ $max=$j; } } $item=$arr[$min]; $arr[$min]=$arr[$i]; $arr[$i]=$item; $item=$arr[$max]; $arr[$max]=$arr[$length-$i-1]; $arr[$length-$i]=$item; } return $arr; } $begin = getCurrentTime(); $arr=ArrayRank(20); print_r($arr); echo "<br/>"; print_r(SimpleSelectionSort($arr)); $end = getCurrentTime(); $spend = $end - $begin; echo "脚本执行时间为:".$spend."\n"; $begin = getCurrentTime(); echo "<br/>"; print_r(TwoElementSelectionSort($arr)); $end = getCurrentTime(); $spend = $end - $begin; echo "脚本执行时间为:".$spend."\n"; ```