PHP实现四种常用O(N^2)级别算法-冒泡,插入,选择,希尔

冒泡排序:

冒牌排序是最经常见的排序算法之一了,因为太简单了,思路正如名字一样,冒泡---把小的往上(前)冒,直到最后有序

function sortArr($arr)  
{  
 $length = count($arr);  
    for($i=0;$i<$length-1;$i++)  
    {  
       for($k=$length-1;$k>$i;$k--){  
         if($arr[$k]<$arr[$k-1]){  
              $arr[$k] = $arr[$k] ^ $arr[$k-1];  
              $arr[$k-1] = $arr[$k] ^ $arr[$k-1];  
              $arr[$k] = $arr[$k] ^ $arr[$k-1];   
         }  
       }  
    }  
  }  

以上为冒泡排序主要代码


插入排序:

首先就是待排序数组第一个默认有序,接着看第二个元素与前面有序元素(即第一个),如果第二个元素小于第一个元素,就把第二个元素插入到第一个元素前面,这样前面两个元素就是有序的;接下来第三个元素先和前面排序好的第二个元素比较,如果比第二个小就插入到第二个元素之前,这样再和第一个元素比较(这么说不会饶吧),然后我们这里注意到,第三个元素要和第二个元素比较,比第二个元素小就插入到第二个元素之前,再和第一个元素比较,如果比第一个元素小,就插入到第一个元素里,那我们是不是可以优化减少交换次数呢?也就是我们省去和第二个元素交换;

假设数组如下,前面两个元素23,25已经有序:

23 25 22 12 8 7

默认情况下22先和25比较,因为比25小,所以插入到25之前

23 22 25 12 8 7

这样有一次交换IO吧,接下来22又和23比较,发生22比23小,于是又交换啦!

我们的优化方法是用一个临时变量$tmp存储待比较的那个值,和前面有序数组比较,如果待比较值小于前面的值,就把前面的值复制一份到他下标下一个元素位置,直到遇到比他小的$tmp就和当前元素交换。

function insertSort($arr)
{    
    $len = count($arr);
	//默认第一个元素有序,所以下标从1开始;
    for($i=1;$i<$len;$i++){
      $tmp = $arr[$i];
      
      for($j=$i;$j>0&&$arr[$j-1]>$tmp;$j--)
      {
          $arr[$j] = $arr[$j-1];
      }
      $arr[$j]=$tmp;
      
    }
  }

选择排序:

感觉和插入排序很像,首先是把数组第一个元素当做是最小的元素,有序啦,然后遍历整个数组,找出最小的一个元素,和第一个元素交换(第一个元素也小于它),于是真正意义上的最小元素就已经在数组开头第一个下标位置了。

function selectionSort(&$array){  
    $len=count($array);  
    for($i=0;$i<$len-1;$i++){  
        $min=$i;  
        for($j=$i+1;$j<$len;$j++){  
    //表明当前最小的还比当前的元素大    
	   min = $array[$min]>$array[$j]?$j:$min;
        }  
            if($min!=$i){  
	$array[$min] = $array[$min] ^ $array[$i];    
        $array[$i] = $array[$min] ^ $array[$i];    
        $array[$min] = $array[$min] ^ $array[$i]; 
        }  
    }
return $array;    
}


希尔排序:

function shell_sort($arr){
    $len = count($arr);
    $f = 3;// 定义因子
    $h = 1;// 最小为1
    while ($h < $len/$f){
        $h = $f*$h + 1; // 1, 4, 13, 40, 121, 364, 1093, ...
    }

    while ($h >= 1){ 
        for ($i = $h; $i < $len; $i++){  
            for ($j = $i; $j >= $h;  $j -= $h){
                if ($arr[$j] < $arr[$j-$h]){
                    $temp = $arr[$j];
                    $arr[$j] = $arr[$j-$h];
                    $arr[$j-$h] = $temp;
                }
            }
        }
        $h = intval($h/$f);
    }
    
}


希尔排序是基于插入排序的,正如插入排序,如果我的最小值在最后面,那么他是不是需要N-1次移动,希尔排序改进了这个缺点。希尔排序思想是使数组任意间隔为h的元素都是有序,比如某个时间这个h是3,也就是数组第一个,第四个,第七个……为一组有序,第二个,第五个,第八个为一组有序^-^懂了吧,此文虽然说是O(N^2)级别算法,但是希尔排序是突破了这个限制的,严格来说比O(N^2)快很多。

emmm相信很多人会有疑问$h为什么要这么设置,其实这个问题不好说,算法一书也说至今无法证明哪一个递增序列是最好的,而使用递增序列1,4,13,40,121,364……所需要的比较次数不会超出N的若干倍乘以递增序列长度,并且大量的实验证明平均每个增幅所带来的比较次数约为N1/5



猜你喜欢

转载自blog.csdn.net/m0_37752084/article/details/79857621