php几种常见排序算法
<?php
//从时间上来看,快速排序和归并排序在时间上比较有优势,
//但是也比不上sort排序,归并排序比较占用内存!
$arr = [4,6,1,2,3,89,56,34,56,23,65];
/**
* 冒泡排序
* 它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。
* 走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成
*/
function BubbleSortq($arr)
{
$len = count($arr);
//设置一个空数组 用来接收冒出来的泡
for ($i = 1; $i < $len; $i++) //该层循环控制 需要冒泡的轮数
{
$flag = false; //本趟排序开始前,交换标志应为假
//该层循环用来控制每轮 冒出一个数 需要比较的次数
for ($k = 0; $k < $len - $i - 1; $k++)
{
//从小到大排序
if ($arr[$k] > $arr[$k + 1])
{
$tmp = $arr[$k + 1];
$arr[$k + 1] = $arr[$k];
$arr[$k] = $tmp;
$flag = true;
}
}
if(!$flag) return $arr;
}
}
// print_r(BubbleSort($arr));
/**
* 选择排序算法
* 每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。
* 选择排序是不稳定的排序方法(比如序列[5, 5, 3]第一次就将第一个[5]与[3]交换,导致第一个5挪动到第二个5后面)
*/
function SelectSort($arr)
{
//定义进行交换的变量
$temp = 0;
for ($i = 0; $i < count($arr) - 1; $i++)
{
$minval = $arr[$i];//假设$minval就是最小的值
$minvalIndex = $i;//最小值的下标
for ($j = $i + 1; $j < count($arr); $j++)
{
if ($minval > $arr[$j])//从小到大排列
{
$minval = $arr[$j];//找最小值
$minvalIndex = $j;
}
}
$temp = $arr[$i];
$arr[$i] = $arr[$minvalIndex];
$arr[$minvalIndex] = $temp;
}
return $arr;
}
// print_r(SelectSort($arr));
/**
* 插入算法
* 每步将一个待排序的纪录,按其关键码值的大小插入前面已经排序的文件中适当位置上,直到全部插入完为止。
* 算法适用于少量数据的排序,时间复杂度为O(n^2)。是稳定的排序方法。
*/
function insertSort($arr)//从小到大排列
{
//先默认$arr[0],已经有序,是有序表
for ($i = 1; $i < count($arr); $i++)
{
$insertval = $arr[$i];//$insertval是准备插入的数
$insertIndex = $i - 1;//有序表中准备比较的数下标
while ($insertIndex >= 0 && $insertval < $arr[$insertIndex])
{
$arr[$insertIndex + 1] = $arr[$insertIndex];//将数组往后挪
$insertIndex--;//将下标往前挪,准备与前一个进行比较
}
if ($insertIndex + 1 !== $i)
{
$arr[$insertIndex + 1] = $insertval;
}
}
return $arr;
}
// print_r(insertSort($arr));
/*
* 快速排序法
* 通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,
* 然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
*/
function quickSort($arr)
{
//判断是否为数组
if (is_array($arr))
{
return false;
}
//如果数组长度为1直接返回
if (!isset($arr[1]))
{
return $arr;
}
$mid = $arr[0]; //获取一个用于分割的关键字,一般是首个元素
$leftArray = array();
$rightArray = array();
foreach ($arr as $v)
{
if ($v > $mid)
{
$rightArray[] = $v; //把比$mid大的数放到一个数组里
}
if($v < $mid)
{
$leftArray[] = $v; //把比$mid小的数放到另一个数组里
}
}
$leftArray = quickSort($leftArray); //把比较小的数组再一次进行分割
$leftArray[] = $mid; //把分割的元素加到小的数组后面,不能忘了它哦
$rightArray = quickSort($rightArray); //把比较大的数组再一次进行分割
return array_merge($leftArray,$rightArray); //组合两个结果
}
// print_r(quickSort($arr));
/**
* 归并排序
* 归并排序是指将两个或两个以上有序的数列(或有序表),合并成一个仍然有序的数列(或有序表)。
* 这样的排序方法经常用于多个有序的数据文件归并成一个有序的数据文件。
*/
function mergeSort(&$arr)
{
$len = count($arr);//求出数组长度
mSort($arr,0,$len - 1);
return $arr;
}
//实际实现归并排序的程序
function mSort(&$arr,$left,$right)
{
if ($left < $right)
{
//说明子序列内存在多余1个的元素,那么需要拆分,分别排序,
//合并计算拆分的位置,长度/2 取整
$center = floor(($left + $right) / 2);
//递归调用对左边进行再次排序
mSort($arr, $left, $center);
//递归调用对右边进行再次排序
mSort($arr, $center + 1, $right);
//合并排序结果
mergeArray($arr, $left, $center, $right);
}
}
//讲两个有序数组合并成一个有序数组
function mergeArray(&$arr, $left, $center, $right)
{
//设置两个起始位置标记
$a_i = $left;
$b_i = $center + 1;
while ($a_i <= $center && $b_i <= $right)
{
//当数组A和数组B都没有越界时
if ($arr[$a_i] < $arr[$b_i])
{
$temp[] = $arr[$a_i++];
}
else
{
$temp[] = $arr[$b_i++];
}
}
//判断 数组A内的元素是否都用完了,没有的话将其全部插入到C数组内
while ($a_i <= $center)
{
$temp[] = $arr[$a_i++];
}
//判断 数组A内的元素是否都用完了,没有的话将其全部插入到C数组内
while ($b_i <= $right)
{
$temp[] = $arr[$b_i++];
}
//将$arrC内排序好的部分,写入到$arr内
for ($i = 0, $len = count($temp); $i < $len; $i++)
{
$arr[$left + $i] = $temp[$i];
}
}
// print_r(mergeSort($arr));
/*
* 希尔排序
* 将数组按指定步长分隔成若干子序列,然后分别对子序列进行排序(在这是直接)
*/
function shellSort($arr)
{
$len = count($arr);
$k = floor($len / 2);
while ($k > 0)
{
for ($i = 0; $i < $k; $i++)
{
for ($j = $i; $j < $len, ($j + $k) < $len; $j = $j + $k)
{
if ($arr[$j] > $arr[$j + $k])
{
$tmp = $arr[$j + $k];
$arr[$j + $k] = $arr[$j];
$arr[$j] = $tmp;
}
}
}
$k = floor($k / 2);
}
return $arr;
}
// print_r(shellSort($arr));
/*
*堆排序
*调整子堆的为大根堆的过程,$s为子堆的根的位置,$m为堆最后一个元素位置
*/
function heapAdjust(&$arr, $s, $m)
{
$tmp = $arr[$s];
// 在调整为大根堆的过程中可能会影响左子堆或右子堆
// for循环的作用是要保证子堆也是大根堆
for ($j = 2*$s + 1; $j <= $m; $j = 2*$j + 1)
{
// 找到根节点的左右孩子中的最大者,然后用这个最大者与根节点比较,
// 若大则进行调整,否则符合大根堆的 特点跳出循环
if ($j < $m && $arr[$j] < $arr[$j + 1])
{
$j++;
}
if ($tmp >= $arr[$j] )
{
break;
}
$arr[$s] = $arr[$j];
$s = $j;
}
$arr[$s] = $tmp;
}
// 堆排序
function heapSort($arr)
{
$len = count($arr);
// 依次从子堆开始调整堆为大根堆
for ($i = floor($len / 2 - 1); $i >= 0; $i--)
{
heapAdjust($arr, $i, $len - 1);
}
// 依次把根节点调换至最后一个位置,再次调整堆为大根堆,找到次最大值,
// 依次类推得到一个有序数组
for ($n = $len - 1; $n > 0; $n--)
{
$tmp = $arr[$n];
$arr[$n] = $arr[0];
$arr[0] = $tmp;
heapAdjust($arr, 0, $n - 1);
}
return $arr;
}
print_r(heapSort($arr));
php几种常见排序算法的更多相关文章
- JavaScript版几种常见排序算法
今天发现一篇文章讲“JavaScript版几种常见排序算法”,看着不错,推荐一下原文:http://www.w3cfuns.com/blog-5456021-5404137.html 算法描述: * ...
- Java中几种常见排序算法
日常操作中常见的排序方法有:冒泡排序.快速排序.选择排序.插入排序.希尔排序等. 冒泡排序是一种简单的排序算法.它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来.走访数 ...
- 几种常见排序算法之Java实现(插入排序、希尔排序、冒泡排序、快速排序、选择排序、归并排序)
排序(Sorting) 是计算机程序设计中的一种重要操作,它的功能是将一个数据元素(或记录)的任意序列,重新排列成一个关键字有序的序列. 稳定度(稳定性)一个排序算法是稳定的,就是当有两个相等记录的关 ...
- 几种常见排序算法的java实现
一.几种常见的排序算法性能比較 排序算法 最好时间 平均时间 最坏时间 辅助内存 稳定性 备注 简单选择排序 O(n^2) O(n^2) O(n^2) O(1) 不稳定 n小时较好 直接插入排序 O( ...
- Java的几种常见排序算法
一.所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作.排序算法,就是如何使得记录按照要求排列的方法.排序算法在很多领域得到相当地重视,尤其是在大量数据的处理方面. ...
- 几种常见排序算法的基本介绍,性能分析,和c语言实现
本文介绍6种常见的排序算法,以及他们的原理,性能分析和c语言实现: 为了能够条理清楚,本文所有的算法和解释全部按照升序排序进行 首先准备一个元素无序的数组arr[],数组的长度为length,一个交换 ...
- 几种常见排序算法的C++描述
基本的排序算法有如下特点: 1.几种容易的算法都是以O(N2)排序的 2.Shell排序编程简单,其也是以O(N2)排序的,在实践中用的很多 3.复杂的排序算法往往都是按照O(NlogN)尽心排序的 ...
- 【知了堂学习笔记】java 编写几种常见排序算法2
排序的分类: 1.直接选择排序 它的基本思想是:第一次从R[0]~R[n-1]中选取最小值,与R[0]交换,第二次从R[1]~R[n-1]中选取最小值,与R[1]交换,....,第i次从R[i-1]~ ...
- 【知了堂学习笔记】java 编写几种常见排序算法
排序的分类: 一.交换排序 所谓交换,就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置,交换排序的特点是:将键值较大的记录向序列的尾部移动,键值较小的记录向序列的前部移动. 1.冒泡 ...
随机推荐
- python note 06 编码方式
1.有如下值li= [11,22,33,44,55,66,77,88,99,90],将所有大于 66 的值保存至字典的第一个key中,将小于 66 的值保存至第二个key的值中.即: {'k1': 大 ...
- LAB4
鼠标放上去可以看文件说明,exception则在exception中处理 文件头里面穿信息,为404 out.flush();把以前的全部冲掉了,所以需要放在后面
- https 网络传输安全架设
1:在集群的情况下,不能在tomcat上 架构ssl 而是在总路由nginx上架设具体实现如下截图 非对称加密是当前流行的加密传输方式 证书是什么 . 在浏览器证书查看 证书是访问请求时 https ...
- JavaScript RegExp.$1
我们不生产代码 我们只是代码的搬运工 JavaScript RegExp.$1 RegExp 是javascript中的一个内置对象.为正则表达式. RegExp.$1是RegExp的一个属性,指的是 ...
- windows下 zookeeper
1.zookeeper的安装和配置 下载:http://zookeeper.apache.org/releases.html 把conf目录下的zoo_sample.cfg改名成zoo.cfg,这里我 ...
- gdb调试技巧 找到php执行进程当前执行的代码
假设线上有一段php脚本,突然在某天出问题了,不处理但是进程没有退出.这种情况可能是异常休眠或者是有段死循环代码,但是我们怎么定位呢,我们这个时候最想知道的应该是这个脚本在此刻在做什么吧.这个是gdb ...
- 《Linux就该这么学》第九天课程
这次课程主要学了如何分区以及RAID技术 有扩展分区:扩展分区可以指定sdb*中的*(1~4)为多少,则其他三个为主分区,扩展分区中的逻辑分区sdb*(*从5开始)无扩展分区:四个皆为主分区 RAID ...
- PMP:4.项目整合管理
内容中包含 base64string 图片造成字符过多,拒绝显示
- rand_1tom 产生 rand_1ton
给定一个等概率随机产生1~M的随机函数rand1ToM如下: public int rand1ToM(int m) { return (int) (Math.random() * m) + 1; } ...
- GitHub(从安装到使用)
一.安装Git for Windows(又名msysgit) 下载地址: https://git-for-windows.github.io/ 在官方下载完后,安装到Windows Explore ...