前言

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

冒泡排序法

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

冒泡是从前往后冒,所以,每轮比较的次数也是逐渐减少的,最后一个数不用比较,其时间复杂度为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. CF 149D Coloring Brackets(区间DP,好题,给配对的括号上色,求上色方案数,限制条件多,dp四维)

    1.http://codeforces.com/problemset/problem/149/D 2.题目大意 给一个给定括号序列,给该括号上色,上色有三个要求 1.只有三种上色方案,不上色,上红色, ...

  2. ie版本

    <!--[if lte IE 6]> 自定义代码 <![endif]-->

  3. jquery---- 数组根据值进行删除

    var chooseAttr = []; //serviceId为值 chooseAttr.splice($.inArray(serviceId,chooseAttr),);

  4. Cache index coloring for virtual-address dynamic allocators

    A method for managing a memory, including obtaining a number of indices and a cache line size of a c ...

  5. Hadoop(2)_机器信息分布表

    1.分布式环境搭建 采用4台安装Linux环境的机器来构建一个小规模的分布式集群. 图1 集群的架构 其中有一台机器是Master节点,即名称节点,另外三台是Slaver节点,即数据节点.这四台机器彼 ...

  6. 动态为TextView控件设置drawableLeft图标,并设置间距

    效果图: 重要属性: textView.setCompoundDrawablePadding(4);//设置图片和text之间的间距 textView.setPadding(-5, 0, 0, 0); ...

  7. 剑指Offer面试题33(java版):把数组排成最小的数

    题目:输入一个正整数数组.把数组里面全部的数字拼接排成一个数,打印能拼接出的全部数字中的一个.比如输入数组{3,32.321}.则打印出这3个数字能排成的最小数字321323. 这个题目最直接的做法应 ...

  8. 【C语言】编写函数实现字符串旋转

    //编写函数实现字符串旋转 #include <stdio.h> #include <assert.h> #include <string.h> void reve ...

  9. How to remove focus without setting focus to another control?

    How to remove focus without setting focus to another control? Ask Question up vote 67 down vote favo ...

  10. poj--3630--Phone List(字典树+前缀判断)

    Phone List Time Limit: 1000MS   Memory Limit: 65536KB   64bit IO Format: %I64d & %I64u Submit St ...