面试常见基本题目总结及php实现(第一部分:排序算法)
2017-09-06 23:38
856 查看
稳定性是指假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变
第一部分:排序算法(下面的都是内部排序,只使用内存的排序算法)
1.插入排序(最坏时间复杂度O(n^2),平均时间复杂度O(n^2)),稳定的
就是把前面的排好,然后把后面的往前面中插入。代码如下所示
希尔排序(最优的情况是O(n^(1.3))元素已经排好顺序,最差的情况O(n^2)元素是逆序的),不稳定
按照增量为[n/2,n/4,...1]来进行分组排序,即第0个数和第n/2个数进行插入排序,正常的插入排序从1开始往后进行插入排序,
这里从增量dk开始往后进行插入排序,比较的也是j-dk个数,j每次减dk循环。
每一步增量写一个函数
循环再写一个函数
2.选择排序(简单选择排序和堆排序)
简单选择排序(最坏时间复杂度O(n^2),平均时间复杂度O(n^2)),不稳定
在一趟选择,如果当前元素比一个元素小,而该小的元素又出现在一个和当前元素相等的元素后面,那么交换后稳定性就被破坏了。比较拗口,举个例子,序列5 8 5 2 9,我们知道第一遍选择第1个元素5会和2交换,那么原序列中2个5的相对前后顺序就被破坏了,所以选择排序不是一个稳定的排序算法。
每一步都找剩下的数中最小的(或者最大的)跟剩下的数的最前面互换。代码如下:
就是说要把剩下的数排成大顶堆(根节点都比子节点大)或者小顶堆(根节点都比子节点小),然后把堆顶输出,输出之后将堆底元素(最后一个元素)放入堆顶,(小顶堆为例)然后与左右节点较小的元素交换,这样该节点所在的树就被破坏了,重复前面(为例之后),当该节点到达叶子节点时结束。
在数组中父节点和子节点的下标关系位两个子节点为父节点*2+1和父节点*2+2。
算法分两步:第一步建立堆,第二步输出顶元素;
冒泡排序法(最坏时间复杂度O(n^2),平均时间复杂度O(n^2)),稳定
这个是基本上最好理解的。把每个数和之后的数进行比较,两两交换,把最大或最小的放在最后。
快速排序法(最坏时间复杂度O(n^2),平均时间复杂度O(n*log2n)),不稳定
在中枢元素和a[j]交换的时候,很有可能把前面的元素的稳定性打乱,比如序列为5 3 3 4 3 8 9 10 11,现在中枢元素5和3(第5个元素,下标从1开始计)交换就会把元素3的稳定性打乱,所以快速排序是一个不稳定的排序算法,不稳定发生在中枢元素和a[j] 交换的时刻。
就是选择一个基准元素将数组分为大于他和小于他的两部分,然后对两部分做相同的操作,
递归的代码如下:
注意array_merge()的使用,一定要是几个数组合并,不能是数字
去面试,人家面试官说这个又建了数组,浪费了空间,这个思想是对的,但是大家一般不这么写;
所以更新了算法:(怪不得人家说不用递归)
取最右为标准,从左往右,找出比标准小的,往数组的左边放,循环停止用i来记录左右的区分
快排非递归(面试大神和我说不用卧槽)
4归并排序(最坏时间复杂度O(n*log2n),平均时间复杂度O(n*log2n)),稳定
这个是二路归并排序
就是把两个有序的数组合成一个有序数组,或者把一个待排数组分成好几个数组排序,再合成一个数组。
注:外部排序算法是,将大数据量的数据,分为多个存储在外部,然后按照内部排序方法对每一个进行排序,将排序结果存回去,然后多个文件采用归并排序,从而得到最后的有序的大文件,这里其实还是二路归并。
多路归并排序是就是k个(不是原来的两个)数组每次进行比较,选出最小的(每次进行k-1次比较),再继续排序。
如果使用“败者树”,可以使上面的k-1次比较变为log2k次比较。
败者树就是建立一个k个叶子节点的二叉树,然后进行比较,把败者记录在每个节点处,比较的时候是胜者比较,会记录下胜者不过不在树里。这样建立了败者树之后呢,就有最后的胜者,将胜者输出,胜者所在的那个数组向或者下一个值,然后和自己的父节点进行比较,确定败者,存入节点中,胜者继续向上,找到新的胜者和新的败者树。重复上面步骤。
5基排序(稳定的)和桶排序
第一部分:排序算法(下面的都是内部排序,只使用内存的排序算法)
1.插入排序(最坏时间复杂度O(n^2),平均时间复杂度O(n^2)),稳定的
就是把前面的排好,然后把后面的往前面中插入。代码如下所示
<?php //从小到大 $array=array(12,1,4,2,1,4,6,34,12,2); $arr=Insertsort($array); for($i=0;$i<count($arr);$i++){ print $arr[$i]; print "\n"; } function Insertsort($array){ for($i=1;$i<count($array);$i++){ $x=$array[$i]; $j=$i-1; while($x<$array[$j]&&$j>=0){ $array[$j+1]=$array[$j]; $j--; } $array[$j+1]=$x; } return $array; } ?>
希尔排序(最优的情况是O(n^(1.3))元素已经排好顺序,最差的情况O(n^2)元素是逆序的),不稳定
按照增量为[n/2,n/4,...1]来进行分组排序,即第0个数和第n/2个数进行插入排序,正常的插入排序从1开始往后进行插入排序,
这里从增量dk开始往后进行插入排序,比较的也是j-dk个数,j每次减dk循环。
每一步增量写一个函数
循环再写一个函数
<?php //从小到大 $arr=array(1,3,2,5,1,32,14,3,5,6); $arr=Shellsort($arr); for($i=0;$i<count($arr);$i++){ print $arr[$i]."\n"; } function Shellinsertsort(&$arr,$n,$dk){ if($dk>=1){ print $dk."a"; for($i=$dk;$i<$n;$i++){ if($arr[$i]<$arr[$i-$dk]){ $temp=$arr[$i]; //$a[$i]=$a[$i-$dk]; $j=$i-$dk; while($temp<$arr[$j]&&$j>=0){ $arr[$j+$dk]=$arr[$j]; $j=$j-$dk; } $arr[$j+$dk]=$temp; } } } } function Shellsort($arr){ $n=count($arr); $dk=floor($n/2); while($dk>=1){ Shellinsertsort($arr, $n, $dk); $dk=floor($dk/2); } return $arr; } ?>
2.选择排序(简单选择排序和堆排序)
简单选择排序(最坏时间复杂度O(n^2),平均时间复杂度O(n^2)),不稳定
在一趟选择,如果当前元素比一个元素小,而该小的元素又出现在一个和当前元素相等的元素后面,那么交换后稳定性就被破坏了。比较拗口,举个例子,序列5 8 5 2 9,我们知道第一遍选择第1个元素5会和2交换,那么原序列中2个5的相对前后顺序就被破坏了,所以选择排序不是一个稳定的排序算法。
每一步都找剩下的数中最小的(或者最大的)跟剩下的数的最前面互换。代码如下:
<?php //从小到大 $array=array(12,1,4,2,1,4,6,34,12,2); $arr=Selectsort($array); for($i=0;$i<count($arr);$i++){ print $arr[$i]; print "\n"; } function Selectsort($array){ for($i=0;$i<count($array);$i++){ $min=$i; for($j=$i;$j<count($array);$j++){ if($array[$min]>$array[$j]){ $min=$j; } } $temp=$array[$i]; $array[$i]=$array[$min]; $array[$min]=$temp; } return $array; } ?>堆排序(最坏时间复杂度O(n*log2n),平均时间复杂度O(n*log2n)),不稳定
就是说要把剩下的数排成大顶堆(根节点都比子节点大)或者小顶堆(根节点都比子节点小),然后把堆顶输出,输出之后将堆底元素(最后一个元素)放入堆顶,(小顶堆为例)然后与左右节点较小的元素交换,这样该节点所在的树就被破坏了,重复前面(为例之后),当该节点到达叶子节点时结束。
在数组中父节点和子节点的下标关系位两个子节点为父节点*2+1和父节点*2+2。
算法分两步:第一步建立堆,第二步输出顶元素;
<?php //从大到小 $array=array(12,1,4,2,1,4,6,34,12,2); $arr=Heapsort($array); for($i=0;$i<count($arr);$i++){ print $arr[$i]; print "\n"; } //$array为等待调整的数组 //$i为等待调整的数组元素的位置 //构造小顶堆 function HeapAdjust(&$array,$i,$length){ while(2*$i+1<$length){ $exchagechild=2*$i+1; if($exchagechild+1<$length&&$array[$exchagechild]>$array[$exchagechild+1]){ $exchagechild++; } if($array[$i]>$array[$exchagechild]){ $temp=$array[$i]; $array[$i]=$array[$exchagechild]; $array[$exchagechild]=$temp; } else{ break; } $i=$exchagechild; } } //堆排序 function 4000 Heapsort($array){ //从最后一个非叶结点开始进行建立堆结构 for($i=floor(count($array)/2)-1;$i>=0;$i--){ HeapAdjust($array,$i,count($array)); } //建立好之后开始进行排序 for($i=count($array)-1;$i>0;$i--){ $temp=$array[$i]; $array[$i]=$array[0]; $array[0]=$temp; HeapAdjust($array,0,$i); } return $array; } ?>3.交换排序(冒泡,快速)
冒泡排序法(最坏时间复杂度O(n^2),平均时间复杂度O(n^2)),稳定
这个是基本上最好理解的。把每个数和之后的数进行比较,两两交换,把最大或最小的放在最后。
<?php //从大到小 $array=array(12,1,4,2,1,4,6,34,12,2); $arr=Bubblesort($array); for($i=0;$i<count($arr);$i++){ print $arr[$i]; print "\n"; } //$array为等待调整的数组 //$i为等待调整的数组元素的位置 //构造小顶堆 function Bubblesort($array){ for($i=0;$i<count($array);$i++){ for($j=0;$j<count($array)-$i-1;$j++){ if($array[$j]<$array[$j+1]){ $temp=$array[$j]; $array[$j]=$array[$j+1]; $array[$j+1]=$temp; } } } return $array; } ?>
快速排序法(最坏时间复杂度O(n^2),平均时间复杂度O(n*log2n)),不稳定
在中枢元素和a[j]交换的时候,很有可能把前面的元素的稳定性打乱,比如序列为5 3 3 4 3 8 9 10 11,现在中枢元素5和3(第5个元素,下标从1开始计)交换就会把元素3的稳定性打乱,所以快速排序是一个不稳定的排序算法,不稳定发生在中枢元素和a[j] 交换的时刻。
就是选择一个基准元素将数组分为大于他和小于他的两部分,然后对两部分做相同的操作,
递归的代码如下:
<?php //从大到小 $array=array(12,1,4,2,1,4,6,34,12,2); $arr=Quicksort($array); for($i=0;$i<count($arr);$i++){ print $arr[$i]; print "\n"; } //$array为等待调整的数组 //$i为等待调整的数组元素的位置 //构造小顶堆 function Quicksort($array){ if(count($array)==1){return $array;} $flag=$array[0]; $left=array(); $right=array(); for($i=1;$i<count($array);$i++){ if($array[$i]>$flag){ $left[]=$array[$i]; } else{ $right[]=$array[$i]; } } $x=Quicksort($left); $y=Quicksort($right); $arr=array_merge($x,array($flag),$y); return $arr; } ?>
注意array_merge()的使用,一定要是几个数组合并,不能是数字
去面试,人家面试官说这个又建了数组,浪费了空间,这个思想是对的,但是大家一般不这么写;
所以更新了算法:(怪不得人家说不用递归)
取最右为标准,从左往右,找出比标准小的,往数组的左边放,循环停止用i来记录左右的区分
<?php $arr=array(3,14,5,7,23,54,12); Quicksort($arr,0,count($arr)-1); for($i=0;$i<count($arr);$i++){ print $arr[$i].'a'; } function Quicksort(&$arr,$left,$right){ if($left<$right){ $i=$left-1; $key=$arr[$right]; for($j=$left;$j<$right;$j++){ if($arr[$j]<$key){ $i++; $temp=$arr[$j]; $arr[$j]=$arr[$i]; $arr[$i]=$temp; } } $temp=$arr[$i+1]; $arr[$i+1]=$arr[$right]; $arr[$right]=$temp; Quicksort($arr,$left,$i); Quicksort($arr,$i+2,$right); } } ?>
快排非递归(面试大神和我说不用卧槽)
4归并排序(最坏时间复杂度O(n*log2n),平均时间复杂度O(n*log2n)),稳定
这个是二路归并排序
就是把两个有序的数组合成一个有序数组,或者把一个待排数组分成好几个数组排序,再合成一个数组。
<?php //从大到小 $array=array(12,1,2,4,6,5,4,2,3,4); Mergesort($array,0,count($array)-1); for($i=0;$i<count($array);$i++){ print $array[$i]; print "\n"; } function Merge(&$arr,$startA,$endA,$startB,$endB){ //print $startA.$endA.$startB.$endB."\n"; $i=$startA;$j=$endB;$m=$startA; $arr1=array(); while($startA<=$endA&&$startB<=$endB){ if($arr[$startA]>$arr[$startB]){ $arr1[]=$arr[$startA]; $startA++; } if($arr[$startA]<=$arr[$startB]){ $arr1[]=$arr[$startB]; $startB++; } } if($startA>$endA){ //$arr=array_merge($arr1,array_slice($arr, $startB,$endB)); while($startB<=$endB){ $arr1[]=$arr[$startB]; $startB++; } } if($startB>$endB){ while($startA<=$endA){ $arr1[]=$arr[$startA]; $startA++; } } for(;$i<=$j;$i++){ $arr[$i]=$arr1[$i-$m]; //print $arr[$i]."a"; } } function Mergesort(&$array,$start,$end){ //print $start.$end."\n"; if($start<$end){ $mid=floor(($start+$end)/2); Mergesort($array,$start,$mid); Mergesort($array,$mid+1,$end); Merge($array,$start,$mid,$mid+1,$end); } } ?>
注:外部排序算法是,将大数据量的数据,分为多个存储在外部,然后按照内部排序方法对每一个进行排序,将排序结果存回去,然后多个文件采用归并排序,从而得到最后的有序的大文件,这里其实还是二路归并。
多路归并排序是就是k个(不是原来的两个)数组每次进行比较,选出最小的(每次进行k-1次比较),再继续排序。
如果使用“败者树”,可以使上面的k-1次比较变为log2k次比较。
败者树就是建立一个k个叶子节点的二叉树,然后进行比较,把败者记录在每个节点处,比较的时候是胜者比较,会记录下胜者不过不在树里。这样建立了败者树之后呢,就有最后的胜者,将胜者输出,胜者所在的那个数组向或者下一个值,然后和自己的父节点进行比较,确定败者,存入节点中,胜者继续向上,找到新的胜者和新的败者树。重复上面步骤。
5基排序(稳定的)和桶排序
相关文章推荐
- 面试常见基本题目总结及php实现(第二部分:二叉树遍历)
- PHP实现常见排序算法
- [分享]Php部分常见问题总结
- PHP实现常见排序算法
- php部分常见问题总结
- Php部分常见问题总结
- Php部分常见问题总结
- PHP常见面试题目深入解答分析(二)
- 计算机与网络安全总结(第一部分:基本加解密算法)
- php部分常见问题总结
- 面试常见题目之海量数据排序(编程珠玑总结一)
- Php部分常见问题总结
- 总结了一些常见的排序算法,面试必备啊!<转载>
- PHP实现常见排序算法
- Php部分常见问题总结(强烈推荐)
- PHP中常见排序算法的实现,php
- 总结了一些常见的排序算法,面试必备啊!
- Php部分常见问题总结
- PHP实现常见排序算法
- Php部分常见问题总结第1/2页