<?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几种常见排序算法的更多相关文章

  1. JavaScript版几种常见排序算法

    今天发现一篇文章讲“JavaScript版几种常见排序算法”,看着不错,推荐一下原文:http://www.w3cfuns.com/blog-5456021-5404137.html 算法描述: * ...

  2. Java中几种常见排序算法

    日常操作中常见的排序方法有:冒泡排序.快速排序.选择排序.插入排序.希尔排序等. 冒泡排序是一种简单的排序算法.它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来.走访数 ...

  3. 几种常见排序算法之Java实现(插入排序、希尔排序、冒泡排序、快速排序、选择排序、归并排序)

    排序(Sorting) 是计算机程序设计中的一种重要操作,它的功能是将一个数据元素(或记录)的任意序列,重新排列成一个关键字有序的序列. 稳定度(稳定性)一个排序算法是稳定的,就是当有两个相等记录的关 ...

  4. 几种常见排序算法的java实现

    一.几种常见的排序算法性能比較 排序算法 最好时间 平均时间 最坏时间 辅助内存 稳定性 备注 简单选择排序 O(n^2) O(n^2) O(n^2) O(1) 不稳定 n小时较好 直接插入排序 O( ...

  5. Java的几种常见排序算法

    一.所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作.排序算法,就是如何使得记录按照要求排列的方法.排序算法在很多领域得到相当地重视,尤其是在大量数据的处理方面. ...

  6. 几种常见排序算法的基本介绍,性能分析,和c语言实现

    本文介绍6种常见的排序算法,以及他们的原理,性能分析和c语言实现: 为了能够条理清楚,本文所有的算法和解释全部按照升序排序进行 首先准备一个元素无序的数组arr[],数组的长度为length,一个交换 ...

  7. 几种常见排序算法的C++描述

    基本的排序算法有如下特点: 1.几种容易的算法都是以O(N2)排序的 2.Shell排序编程简单,其也是以O(N2)排序的,在实践中用的很多 3.复杂的排序算法往往都是按照O(NlogN)尽心排序的 ...

  8. 【知了堂学习笔记】java 编写几种常见排序算法2

    排序的分类: 1.直接选择排序 它的基本思想是:第一次从R[0]~R[n-1]中选取最小值,与R[0]交换,第二次从R[1]~R[n-1]中选取最小值,与R[1]交换,....,第i次从R[i-1]~ ...

  9. 【知了堂学习笔记】java 编写几种常见排序算法

    排序的分类: 一.交换排序 所谓交换,就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置,交换排序的特点是:将键值较大的记录向序列的尾部移动,键值较小的记录向序列的前部移动. 1.冒泡 ...

随机推荐

  1. protobuf shutdownprotobuflibrary的时候crash,释放的指针出错

    往往是多个子项目中有多次链接使用. 解决方法: 1. 使用静态库. 2. issure中有说2.6.1还未允许多次释放,建议使用3.4.x版本. 参考: https://github.com/prot ...

  2. strcpy函数用法

    字符串是数组类型,不能通过赋值运算进行,要通过strcpy进行拷贝,其中目的字符串必须是字符串变量,源字符串可以是常量,复制后源字符串保持不变. strcpy()是C中的一个复制字符串的库函数,在C+ ...

  3. 【Spark2.0源码学习】-7.Driver与DriverRunner

         承接上一节内容,Client向Master发起RequestSubmitDriver请求,Master将DriverInfo添加待调度列表中(waitingDrivers),下面针对于Dri ...

  4. [Python] 怎么把HTML的报告转换为图片,利用无头浏览器

    How to convert HTML Report to picture format in Email? So that we can see the automation report also ...

  5. Python select模块学习

    select 是常用的异步socket 处理方法 一般用法: # iwtd,owtd,ewtd 分别为需要异步处理的读socket队列, 写socket队列(一般不用), 和错误socket队列, 返 ...

  6. Windows查看服务

    开始→运行(Windows+R快捷键也能调出运行)→输入:services.msc→确定

  7. django的简单原理

    一.自定义客户端和服务端的请求响应 1.客户端打开url,向服务器发出请求 2.服务端用socket写一个py,用于接收请求和做出响应 3.服务端接收请求 4.服务端模拟HTTP协议做出响应,状态行为 ...

  8. HTML5 添加新的标签 input属性

    <!-- 新增 有语意标签 --> <nav></nav> <!-- 导航标签 --> <seclion></seclion> ...

  9. python模块:configparser

    """Configuration file parser. A configuration file consists of sections, lead by a &q ...

  10. visual studio 2017使用技巧

    visual studio 2017使用技巧 批量删除代码中的空白行 Ctrl + H, 查找: ^(?([^\r\n])\s)*\r?$\r?\n 替换: 使用正则表达式 当前文档 常用快捷键 注释 ...