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.冒泡 ...
随机推荐
- 106. Construct Binary Tree from Inorder and Postorder Traversal根据后中序数组恢复出原来的树
[抄题]: Given inorder and postorder traversal of a tree, construct the binary tree. Note:You may assum ...
- maven 监理web war 项目
- 33.MySQL高可用架构
33.高可用架构33.1 MMM架构MMM(Master-Master replication manager for MySQL)是一套支持双主故障切换和双主日常管理的脚本程序(Perl).主要用来 ...
- Android开发之页面跳转传递list集合
这篇随笔这里详细记录两个activity之间如何传递list集合中的数据. 1.首先要对javabean进行序列化处理,即实现Serializable. package com.anhua.bean; ...
- PHP 获取周,月列表
PHP的date函数以及strtotime函数是很强大的.基本上围绕这2个函数就能处理绝大多数日常开发中日期的处理. 假设有一个需求是按周,月获取最近7周和最近7月的查询.那么我们肯定要划分出时间区间 ...
- 2019年Python数据挖掘就业前景前瞻
Python语言的崛起让大家对web.爬虫.数据分析.数据挖掘等十分感兴趣.数据挖掘就业前景怎么样?关于这个问题的回答,大家首先要知道什么是数据挖掘.所谓数据挖掘就是指从数据库的大量数据中揭示出隐含的 ...
- tween 缓动动画
在讲tween类之前,不得不提的是贝塞尔曲线了.首先,贝塞尔曲线是指依据四个位置任意的点坐标绘制出的一条光滑曲线.它在作图工具或动画中中运用得比较多,例如PS中的钢笔工具,firework中的画笔等等 ...
- Python3实战系列之八(获取印度售后数据项目)
问题:续接上一篇.说干咱就干呀,勤勤恳恳写程序呀! 目标:此篇开始进入正题了.为实现我们整个项目功能而开始实现各个子模块功能.首先实现第一篇列出的分步功能模块的第五步: 5.python连接SQL S ...
- Object.defineProperty之observe实现
对数据对象的属性批量劫持设置: <script type="text/javascript"> function observe(data){ if(!data || ...
- ----关于posotion的sticky与fixed的区别----
sticky 出现在正常流当中,不能设置定位,随页面滚动 (sticky = relative + fixed) fixed 不出现在正常流当中,能设置定位,随页面滚动 eg: html: <p ...