前言

虽然工作中,你觉得自己并没有涉及到算法这方面的东西,但是算法是程序的核心,一个程序的好与差,关键是这个程序算法的优劣,所以对于冒泡排序、插入排序、选择排序、快速排序这四种基本算法,我想还是要掌握的。

冒泡排序法

冒泡排序大概的意思是依次比较相邻的两个数,然后根据大小做出排序,直至最后两位数。由于在排序过程中总是小数往前放,大数往后放,相当于气泡往上升,所以称作冒泡排序。

冒泡是从前往后冒,所以,每轮比较的次数也是逐渐减少的,最后一个数不用比较,其时间复杂度为O(n²),算法如下:


/**
* 冒泡排序算法
* @param array $arr
* @return array
*/
function bubble_sort($arr) {
// 判断参数是否为数组,且不为空
if (!is_array($arr) || empty($arr)) {
return $arr;
}
// 循环需要冒泡的轮数
for ($i = 1, $len = count($arr); $i < $len; $i++) {
// 循环每轮需要比较的次数
for ($j = 0; $j < $len - $i; $j++) {
// 大的数,交换位置,往后挪
if ($arr[$j] > $arr[$j + 1]) {
$temp = $arr[$j + 1];
$arr[$j + 1] = $arr[$j];
$arr[$j] = $temp;
}
}
}
return $arr;
}

选择排序法

选择排序的原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾;以此类推,直到所有元素均排序完毕。

选择是每一次从假定一个最小值的位置,然后用假定最小值和后面的值依次比较,找到实际的最小值来放到假定最小值的位置上,其时间复杂度也为O(n²),算法如下:


/**
* 选择排序法
* @param array $arr
* @return array
*/
function select_sort($arr) {
// 判断参数是否为数组,且不为空
if (!is_array($arr) || empty($arr)) {
return $arr;
}
$len = count($arr);
for ($i = 0; $i < $len - 1; $i++) {
// 假设最小数的位置
$min = $i;
// 用假设的最小数和$i后面的数循环比较,找到实际的最小数
for ($j = $i + 1; $j < $len; $j++) {
// 后面的数比假设的最小数小,替换最小数
if ($arr[$min] > $arr[$j]) {
$min = $j;
}
}
// 假设的最小数和实际不符,交换位置
if ($min != $i) {
$temp = $arr[$min];
$arr[$min] = $arr[$i];
$arr[$i] = $temp;
}
}
return $arr;
}

插入排序法

插入排序的原理:每次将一个待排序的记录,按其关键字大小插入到前面已经排好序的子序列中的适当位置,直到全部记录插入完成为止。

插入排序法是先将排序元素的前两个元素排序,然后将第三个元素插入已经排序好的两个元素中,所以这三个元素仍然是从小到大排序,接着将第四个元素插入,重复操作直到所有元素都排序好;其时间复杂度同样为O(n²),算法如下:


/**
* 插入排序法
* @param array $arr
* @return array
*/
function insert_sort($arr) {
// 判断参数是否为数组,且不为空
if (!is_array($arr) || empty($arr)) {
return $arr;
}
$len = count($arr);
for ($i = 1; $i < $len; $i++) {
// 当前需要比较的临时数
$tmp = $arr[$i];
// 循环比较临时数所在位置前面的数
for ($j = $i - 1; $j >= 0; $j--) {
// 前面的数比临时数大,则交换位置
if ($arr[$j] > $tmp) {
$arr[$j + 1] = $arr[$j];
$arr[$j] = $tmp;
}
}
}
return $arr;
}

快速排序法

快速排序法是对冒泡排序的一种改进。他的基本原理是:通过一趟排序将待排记录分割成独立的两部分,其中一部分的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行快速排序,整个排序过程可以递归进行,以达到整个序列有序的目的。

快速排序法是从数列中挑出第一个数(最后一个数)作为基准元素,然后循环所有数,和基准书比较分为左右两列,然后重复这样的步骤继续划分为左右两列,算法如下:


/**
* 快速排序法
* @param array $arr
* @return array
*/
function quick_sort($arr) {
// 判断参数是否为数组,且不为空
if (!is_array($arr) || empty($arr)) {
return $arr;
}
// 数组长度为1停止排序
$len = count($arr);
if ($len == 1) {
return $arr;
}
// 声明左右两个空数组
$left = $right = [];
// 循环遍历,把第一个元素当做基准数
for ($i = 1; $i < $len; $i++) {
// 比较当前数的大小,并放入对应的左右数组
if ($arr[$i] > $arr[0]) {
$right[] = $arr[$i];
} else {
$left[] = $arr[$i];
}
}
// 递归比较
$left = quick_sort($left);
$right = quick_sort($right);
// 左右两列以及基准数合并
return array_merge($left, [$arr[0]], $right);
}

使用方法

声明一个待排序的数组,然后调用对应的排序方法即可得到返回的排序好的数组;说明一下,我这里的排序设计都是递增的,如果需要递减,需要修改一下排序算法的比较替换符就行。


// 待排序数组
$arr = [1, 4, 5, 9, 3, 8, 6];
// 调用排序方法
$sort_arr = bubble_sort($arr);
// 输出打印
print_r($sort_arr);

分析算法

通常,对于一个给定的算法,我们要做两项分析:第一是从数学上证明算法的正确性,这一步主要用到形式化证明的方法及相关推理模式,如循环不变式、数学归纳法等。而在证明算法是正确的基础上,第二步就是分析算法的时间复杂度。算法的时间复杂度反映了程序执行时间随输入规模增长而增长的量级,在很大程度上能很好反映出算法的优劣与否。还有我们通常说的:算法优化无非就是以时间换空间,以空间换时间,一般这两者是不可兼得。

结束语

实现一个程序,肯定是有多种算法的,大家有其他想说的,都可以留言和我交流,谢谢!如有问题,也欢迎指出,我会及时改正,谢谢!

原文地址:https://segmentfault.com/a/1190000016451705

PHP算法之四大基础算法的更多相关文章

  1. JavaScript数据结构与算法(五) 数组基础算法

  2. PHP基础算法

    1.首先来画个菱形玩玩,很多人学C时在书上都画过,咱们用PHP画下,画了一半. 思路:多少行for一次,然后在里面空格和星号for一次. <?php for($i=0;$i<=3;$i++ ...

  3. 10个经典的C语言面试基础算法及代码

    10个经典的C语言面试基础算法及代码作者:码农网 – 小峰 原文地址:http://www.codeceo.com/article/10-c-interview-algorithm.html 算法是一 ...

  4. Java基础算法集50题

    最近因为要准备实习,还有一个蓝桥杯的编程比赛,所以准备加强一下算法这块,然后百度了一下java基础算法,看到的都是那50套题,那就花了差不多三个晚自习的时间吧,大体看了一遍,做了其中的27道题,有一些 ...

  5. 贝叶斯公式由浅入深大讲解—AI基础算法入门

    1 贝叶斯方法 长久以来,人们对一件事情发生或不发生的概率,只有固定的0和1,即要么发生,要么不发生,从来不会去考虑某件事情发生的概率有多大,不发生的概率又是多大.而且概率虽然未知,但最起码是一个确定 ...

  6. 2018-02-03-PY3下经典数据集iris的机器学习算法举例-零基础

    ---layout: posttitle: 2018-02-03-PY3下经典数据集iris的机器学习算法举例-零基础key: 20180203tags: 机器学习 ML IRIS python3mo ...

  7. 贝叶斯公式由浅入深大讲解—AI基础算法入门【转】

    本文转载自:https://www.cnblogs.com/zhoulujun/p/8893393.html 1 贝叶斯方法 长久以来,人们对一件事情发生或不发生的概率,只有固定的0和1,即要么发生, ...

  8. java入门学习(3)—循环,选择,基础算法,API概念

    1.顺序结构:也就是顺着程序的前后关系,依次执行.2.选择分支:利用if..else , / switch(){case [ 这个必须是常量]:}; / if..else if….. ….else.. ...

  9. Java - 冒泡排序的基础算法(尚学堂第七章数组)

    /** * 冒泡排序的基础算法 */ import java.util.Arrays; public class TestBubbleSort1 { public static void main(S ...

随机推荐

  1. 2016年工作中遇到的问题1-10:select-for-update锁表

    1.select... for update锁表.注意事项:事务下使用,@Transactional如果用主键,只锁住1行记录如果不用主键,会锁住多条记录,mysql下测试,查询1条,锁住1行,查询2 ...

  2. VUEX 总结

    What is Vuex? vuex是一个专为Vue.js应用程序开发的状态管理模式.他采用集中式储存管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变换 VUEX并不限制你的代 ...

  3. OA项目知识总结2

    BaseAction的抽取 项目中的每个实体类都对应一个action  每个action都都要继承ActionSupport类 已以及实现ModelDriver接口  并且需要注入service 虽然 ...

  4. BA-给排水-供水系统自动控制(转载)

    浙江省建筑设计研究院划 杨绍胤 杨庆 摘 要:探讨供水系统变流量和恒压自动控制和设计方法.关键词: 供水系统 自动控制 传统给水系统常在屋顶设置高位水箱.水从地下水箱用水泵打到高位水箱.从高位水箱通过 ...

  5. 使用Eclipse进行远程调控

    什么是远程调试,就是在A机器上利用Eclipse单步跟踪调试B机器上的Web应用,当然调试A机器上Web应用也是没有问题的,90%我都是调试本机的Web应用,远程调试的意义我想我不用说了,大家都会想到 ...

  6. Mina airQQ聊天 client篇(三)

    开发工具 (FlashBuilder4.7) 程序类型(Adobe Air) Flex Air做的桌面程序,效果还挺好看的.最主要是Socket这一块,它也是异步的,而且在Flex中的事件机制比較强大 ...

  7. php面向对象之get和set方法

    php面向对象之get和set方法 简介 1.自己写get或者set 2.用系统的魔术方法__get和__set 代码 <?php class Person{ private $userName ...

  8. 使用Chrome插件Postman进行简单的Get/Post测试

    转自:https://blog.csdn.net/dearmorning/article/details/56854236 Postman插件: 一种网页调试与发送网页http请求的chrome插件, ...

  9. 对python变量的理解

    #!/usr/bin/python class Person: '''some words content or descriptions!''' name='luomingchuan' _age = ...

  10. C# 遍历文件夹及子目录下所有图片.

    要求:取指定目录下面的所有图片,以表格的型式展示并显示该图片的相对路径. 服务端代码: public partial class ViewIcon : System.Web.UI.Page { JAr ...