开发中用到的一个快速排序法

实际上在,做web开发,比较少遇到使用一些算法之类的,毕竟不是做搜索引擎,也不是写底层(比如写个类似于mysql这样的数据库,里面需要自己实现排序算法),另外,每种语言,比如java,php都或多或少已经封装好排序函数给程序员使用。比如有个共识,大家做web开发的基本都明白,业务逻辑多比较简单,不是很复杂的业务逻辑。我们作为web开发的程序员,基本是是web架构,对数据库增删查改数据,然后把数据展示在页面中,大多就是涉及性能优化,缓存等等。

 

学学一些常见的算法,对于实现特殊的应用还是有帮助的。比如有些时候我们依赖于数据库中order by来实现排序了,所以非常习惯直接接下交给数据库实现排序了。

​

接下来,我就遇到需要自己实现排序了。

 

​因为我们在实际开发中,遇到一个问题,完全需要我自己实现排序。需求如下:

 

在商品表里面,有一个字段是goods_price(商品价格),现在要开发一个促销价功能。促销价有个时间范围设置。在前台页面中,展示商品的时候。如果当前时间符合促销时间。就要按照促销价格执行。于是促销价就单独增加了一个字段来保存,叫做promote_price,促销时间配置信息比如什么时间,每天几点到几点之类的时间设置信息暂时不管,存储在其他字段中的,展示的时候,要用当前时间跟配置的时间进行比较。

单条商品展示的时候,就直接判断是否在促销时间内即可了。没遇到排序的问题。

 

而是在做商品列表页面的时候,一个这样的小细节就让我发现需求:用户可以选择商品价格按照"从高到低"也可以选择"从低到高"排序。

如果是单纯排序,以往是直接交给数据库去排序,一般我们习惯了sql中使用"order by goods_price DESC"之类的语句就能实现按照价格降序还是升序进行。

 

现在,不能简单就按照goods_price(商品价格)排序就ok。比如当前时间有的商品是符合促销时间的,那么促销价也是要作为排序的。

 

简单的 order by goods_price DESC,promote_price DESC 这种做法的话完全是不对路现在的需求。

 

所以呢,需要先对交给数据库的order by goods_price DESC 排序一次,列出数据。
然后遍历,看哪些商品数据是符合促销价格的。然后自己编写代码实现排序。
 

我初期想法是:拿到当前页的数据,里面判断每行是否符合促销价时间点

foreach(经过数据库按照价格字段排序的结果)
{
if ($v['promote_price'] > 0 && $promote_class->promtoe_validate($food_info)) {
            $v['is_promote'] = true;             $v['price']= $v['promote_price'];//将原价改为促销价显示
        }

}


//对上面的列表,因为上面的列表经过mysql排序一次后,还经过了促销价。所以还需要再次编写一个排序算法排序一次。这样就可以把促销价低的放到前面去了

 
 
 

其实,mysql数据库就是用c语言编写的。我理解数据库order by,它的排序也就是用c语言实现对数组的排序(关系表里面返回的的行列表就是一个二维数组)

 

只是,平时我们排序是交给数据库去实现了。很少自己编写,所以因为接触不多,就以为这些算法自己用不上,现在仍然需要用php语言对数据去实现排序。

 

数据库中的 order by a DESC,b ASC  的实现原理猜测?
 
第一种理解:先按照a字段进行排序。然后又对数据按照b字段进行排序。
第二种理解:先按照a字段进行排序 ,如果遇到两个值相同的,无法确定谁在前在后时,则使用b asc来确定两个数据的先后顺序。
 
我是第一种理解,后来纠正,第二种理解才是对符合对的,因为这才比较符合设计的考虑点:

为什么要设计可以多个字段进行排序?难道是为了相互覆盖掉吗?比如先按照a字段排序了。某两项数据本来是一个在前一个在后,如果又按照b asc进行排序,那么可能原来这两项数据的顺序就可能错位,就是可能导致后面的排序规则应用后的结果覆盖前面的。

 

 

假设数据库排序是这样子设计的话就没实际意义了。之所以设计多个字段进行排序。就是为了解决,遇到两行中a字段的值都2,2的时候,怎么确定先后?这个时候就调用后面的排序规则对这两项数据排序。所以order by 后面的字段先后顺序不同造成的效果是不同的。

现实生活例子:假设要排名100个学生的英语成绩,假设排序的时候,遇到三个学生都是88分。谁排名在前呢?这个时候可以附加一种新的排序方式,对这三个学生看他们的品行分排序。这样子就好确定了。

 

 

 

 

网上的快速排序法,实现都是针对一维数组来实现的。现在我要模拟数据库中的行,也就是二维数组作为参数,并且可以指定任意字段作为排序方式。

比如从数据库中查询出一个数据列表,原封不动的对这个列表可以指定某个字段进行排序(数据库就是实现这个需求吧。当然他们要先进得些。人家牛逼些 呵呵。

 

具体,看下面

 

/*

 * 排序:此函数是一个通用函数,只要是二维数组的排序都可以调用。初衷是解决价格快速排序(涉及到促销价,无法使用order by解决)

 * +--------------------------------------------------------------------------

 * @param $arr 要排序的数组,二维数组。对应就是数据库中的多行数据 array(

 * 0=>array("字段1"=>'','字段2'=>''...)

 * 1=>array("字段1"=>'','字段2'=>''...)

 * 2=>array("字段1"=>'','字段2'=>''...)

 * )

 * +--------------------------------------------------------------------------

 * @param $key_field 按照哪个字段进行排序,不要传入一个并不存在的字段。会打乱原来的顺序

 * +--------------------------------------------------------------------------

 * @param $sort_type = asc or desc  排序方式。从小大到大,还是从大到小

 */

 

function quickSort($arr, $key_field, $sort_type = "asc") {

    if (count($arr) > 1) {

        //使用哪个字段排序,先得到该字段所有数据,目的是转换成一维数组进行排序

        $key_value_arr = array();

        $return_arr = array();

 

        //先判断排序的字段是否存在

 

 

        foreach ($arr as $k => $v) {

            $key_value_arr[$k] = $v[$key_field]; //得到这个字段的值

        }

 

        //php内置函数实现了按降序还是升序排,但是只支持一维数组

        if ($sort_type == 'desc') {

            arsort($key_value_arr);

        } else {

            asort($key_value_arr);

        }

        reset($key_value_arr);

        foreach ($key_value_arr as $k => $v) {

            $return_arr[$k] = $arr[$k]; //得到行

        }

 

        return $return_arr;

    } else {

        return $arr;

    }

}

 

---------------------------------------------------------------------------

总结一下我对快速排序法的理解

--------------------------------------------------------------------------

 

假设有100个元素,对此进行排序。那么需要遍历多少次呢?仍然需要遍历至少100次。因为确实都免不了,逐个去扫描每个元素,丢到左边,还是右边。当第一次分割之后。还要继续对分割后两边的进行重复这一步骤。

 

当元素数量小的时候,是体会不到区别的。如果数量很大,达到上万个元素。需要进行排序,则需要涉及到算法了

 

比如比较高矮,现实中情况,我们人可以用眼睛来看,哪个更小,然后认为的排序出来。但是计算机则不同。我们必须编写程序来告诉它要什么样的方法实现。

快速排序体现的思想是:分治法。分割成小块,逐个解决。

 

大体的思路描述:

1、从一堆数据里面找到一个基准的数据。按照这个数据标准分割开来。现实例子,一堆人100个人,比较高矮。现在我找出一个高度的人,我按照这个人的身高,分成a,b两组。比他矮的都站到a组,比他高的都站到b(跟他一样高的随便放哪一边都可以),这样子可将100个人分割成两组人。

 

结果是,a组里面的所有人身高都要<=b组里面的人。

 

2、对a组里面的人重复第一步。对b组里面的人也重复第一步。

 

3、直到最后只剩下一个(因为已经没法在继续切割了),才分组。

 

 

 

我学到一个思想:先切成大块,然后对每个大块单独处理。最后把各个块的处理结果都合并起来。

 

function quickSort($arr) {
  if(count($arr) > 1) {
    $k=$arr[0];
    $x=array();
    $y=array();
    $_size=count($arr);    
    for($i=1;$i<$_size;$i++) {
      if($arr[$i] <=$k) {
        $x[] =$arr[$i];//小的放这边
      }else{
        $y[] =$arr[$i];//大的放这边。这样子是从小到大排序,如果想从大到小返回,那么调换位置与$x[] =$arr[$i];的位置即可
      }
    }
     //得到分割看来左右两边的数据
    $x= quickSort($x);//左边的数据,对这些数据再次使用分割法排序,返回的结果就是排序后的数据
    $y= quickSort($y);//右边的数据
    returnarray_merge($x,array($k),$y);
  }else{
    return$arr;
  }

}

 

不正确之处,欢迎指正!

 

 

代码备份:

复制代码
<?php

//大体思路:由于是二维数组。所以先得到指定key的所有值。也就是转换为一维数组了。

/*
不过这个一维数组的key要使用二维数组的key。这样子一维数组排序后,方便对应到二维数组中去。就是靠这个key。


一维数组如下:
array('1'=>'a','4'=>''b','3'=>'c','5'=>'d');

1,2,4这些key值,到时候就是对应到里面去的证据


思考,如果还要加一个条件呢比如像sql那样子的:order by a,b,c
当a字段的值都相等的情况下,就启用b字段进行排序。如果还是相等,则启用c字段进行排序。

*/




/*
$keys = array();

$keys['gg'] = '8.9';
$keys[1] = '8.8';

$keys[5] = '7.5';




asort($keys);//排序有个特点,原来的key值不会改变的。只是把位置换一下。我之前以为是调换了key值。这样子,0,1,2,3,4

reset($keys);
var_dump($keys);

*/




/*
 * +-------------------------------------------------------
 * 快速排序
 * @author wangtao 2015.6.10
 * +-------------------------------------------------------
 * @param $arr 要排序的数组,二维数组。对应就是数据库中的多行数据
  array(
 * 0=>array("字段1"=>'','字段2'=>''...)
 * 1=>array("字段1"=>'','字段2'=>''...)
 * 2=>array("字段1"=>'','字段2'=>''...)
 * )
 * @param $key_field 按照哪个字段进行排序
 * @param $sort_type = asc or desc  排序方式。从小大到大,还是从大到小
 * +-------------------------------------------------------
 * return 按照指定排序后的一个新数组。原来的key仍然会保留
 * 如:1=>array("字段1"=>'','字段2'=>''...),2=>array("字段1"=>'','字段2'=>''...)  
 * 按照"字段2"排序后,key为2元素可能在前面前面了,但是key值不会被修改,会原样保留
 * +-------------------------------------------------------
 */

function quick_sort($arr, $key_field, $sort_type = "asc") {
    if (count($arr) > 1) {
        //使用哪个字段排序,先得到该字段所有数据,目的是转换成一维数组进行排序
        $key_value_arr = array();
        $return_arr = array();
        //先判断排序的字段是否存在,如果字段根本不存在,避免打乱原来数组的顺序

    
        foreach ($arr as $k => $v) {
            @ $key_value_arr[$k] = $v[$key_field]; //得到这个字段的值

        }

        //php内置函数实现了按降序还是升序排,但是只支持一维数组
        if ($sort_type == 'desc') {
            arsort($key_value_arr);
        } else {
            asort($key_value_arr);
        }


        reset($key_value_arr);

        foreach ($key_value_arr as $k => $v) {
            $return_arr[$k] = $arr[$k]; //得到行
        }
        //var_dump($return_arr);
        return $return_arr;
    } else {
        return $arr;
    }
}

$array = array(
array('name'=>'手机','brand'=>'诺基亚','price'=>1050),
array('name'=>'笔记本电脑','brand'=>'lenovo','price'=>4300),
array('name'=>'剃须刀','brand'=>'飞利浦','price'=>3100),
array('name'=>'跑步机','brand'=>'三和松石','price'=>4900),
array('name'=>'手表','brand'=>'卡西欧','price'=>960),
array('name'=>'液晶电视','brand'=>'索尼','price'=>6299),
array('name'=>'激光打印机','brand'=>'惠普','price'=>1200),
array('name'=>'手机','brand'=>'诺基亚','price'=>1050),
);

var_dump(quickSort($array,'m'));





//看对一个数组里面元素值都为空的怎么排序
$row = array(
0=>null,
1=>null,
2=>null,
3=>null,
);
asort($row);
var_dump($row);//如果为空。则根据key值倒过来?

/*返回的是array
  3 => null
  2 => null
  1 => null
 0 => null
现在终于明白了,数据库字段中是否保持null,对于排序是有影响的。结果就会影响展示效果。
*/

转载于:https://www.cnblogs.com/haohaoyuan/p/7832622.html

快速排序、冒泡排序等排序测试集 本资源为测试排序的测试集。 其中包括: 1w个0~10000之间的随机数 10w个0~100000之间的随机数 100w个0~1000000之间的随机数 10w个全部为0的文件 立即下载

相关推荐

用位排序和快速排序排30万个数

用位排序和快速排顺序排列30万个数,主要是位排序的算法 30万个数是程序产生的 虽然不推荐中文注释,但是中国人还是喜欢中文的注释,我就是这样的 在linux下,中文注释可能是乱码

快速排序

转载请注明出自flowsky37的博客的博客,尊重他人辛苦劳动! 简介快速排序是应用非常广泛的一种排序算法了。快速排序流行的原因是它实现简单,适用于各种不同的输入数据,而且在一般应用中比其他排序算法都要快得多。快速排序的特点:它是原地排序,只需要一个很小的辅助栈,且将长度为N的数组所需的时间和NlgN成正比。另外,快速排序的内循环比大多数排序算法都要短小,这意味着无论是在理论上还是在实际中都要更快

flowsky37的专栏 443

树莓派4B之OpenCV人脸识别实战:从Haar Cascade到实时检测(保姆级教程)

本教程详细介绍了如何在树莓派4B上部署OpenCV,并利用Haar Cascade算法实现实时人脸识别。内容涵盖从系统环境搭建、算法原理解析到代码逐行讲解与实战调优,为嵌入式AI和计算机视觉初学者提供了一份完整的保姆级实践指南。

p8q9r0的博客 402

SQL中常用的四个排序函数,你用过几个?

ROW_NUMBER()是排序,当存在相同成绩的学生时,ROW_NUMBER()会依次进行排序,他们序号不相同,而Rank()则不一样。如果出现相同的,他们的排名是一样的。今天就给大家介绍四个你不怎么常用排序函数,他们就是SQL Server排序中经常用到的ROW_NUMBER(),RANK(),DENSE_RANK(),NTILE()这四个好兄弟。RANK()是1-1-3-4-5,而ROW_NUMBER()则还是1-2-3-4-5,这就是RANK()和ROW_NUMBER()的区别了。

伤心的辣条 9927

[Pytorch案例实践001]手写MNIST数字识别

Pytorch实现手写数字识别,带完整数据集。

2403_83044722的博客 1115

鸿蒙OpenHarmony南向开发 轻量系统芯片移植指南(一)

OpenHarmony系统采用"系统>子系统>部件"层级架构,支持功能模块化裁剪。本文介绍了关键子系统及移植方法:1)启动恢复子系统负责内核到应用间的进程初始化,需配置启动入口标识及链接脚本;2)文件子系统提供基础文件操作接口,需适配HAL层文件读写功能,可通过Flash模拟、轻量文件系统或厂商自有方案实现。移植过程需修改config.json配置,添加对应组件定义及功能实现。系统采用模块化设计,开发者可根据实际需求灵活配置所需子系统功能。

yx525623的博客 1134

sql对数组元素切分_快速排序的一种优化(三项切分的快速排序算法)

首先,先哔哔下什么是快速排序算法。快速排序由C. A. R. Hoare在1962年提出。基本思想是使一串无序数据,选取其中一条数据,使该数据左边放置全部都是小于该数据的数据,使右边放置大于该数据的数据。这样便完成一趟快速排序,然后可以针对该串数据左边进行下一趟快速排序,右边也进行一趟,这样一次次的进行递归操作,便可得到有序的数据序列。快速排序主要采用的是分治思想。具体算法如下:public st...

weixin_36301639的博客 502

thinkcmf 代码执行 (CVE-2019-7580) 漏洞复现

所有文章,仅供安全研究与学习之用,后果自负! thinkcmf 代码执行 CVE-2019-7580thinkcmf 代码执行 (CVE-2019-7580)0x01 漏洞描述0x02 影响范围0x03 漏洞复现3.1 登录后台3.2 漏洞利用3.2.1webshell3.2 phpinfo3.3 获取系统命令0x04 漏洞修复 thinkcmf 代码执行 (CVE-2019-7580) 复现小心会搞崩环境。 0x01 漏洞描述 ThinkCMF是一款支持Swoole的开源内容管理框架(CMF),基于Thi

YouthBelief的博客 4264

算法设计之快速排序

被问到排序,可能以前一直没用重视它,好高骛远基本功不扎实,这次准备好好整理下快速排序的知识,从而深入研究看看能不能向前推广到其他编程题的应用。 1.算法简介: 原理:快速排序是对冒泡排序的一种改进,首先选择序列中第一个记录为轴值(pivot),然后两边执行冒泡排序找到pivot的位置, 返回pivot的位置,然后两边数组继续叠代。 我觉得快速排序的算法写不出主要原因是 ①冒泡排序理解不深 或...

lishinho的博客 2179

YOLO26 多模态融合技术:RGB+红外/深度/雷达融合

YOLO(You Only Look Once)是一种流行的目标检测算法,其最大特点是快速且端到端地完成图像中所有目标的检测与分类任务。YOLO首次在2016年由Joseph Redmon等人提出,彻底改变了传统目标检测(如R-CNN系列)的思路,被广泛应用于自动驾驶、视频监控、工业质检等场景。

一键难忘的博客 3523

mysql快速排序怎么实现的_开发中用到的一个快速排序法

实际上在,做web开发,比较少遇到使用一些算法之类的,毕竟不是做搜索引擎,也不是写底层(比如写个类似于mysql这样的数据库,里面需要自己实现排序算法),另外,每种语言,比如java,php都或多或少已经封装好排序函数给程序员使用。比如有个共识,大家做web开发的基本都明白,业务逻辑多比较简单,不是很复杂的业务逻辑。我们作为web开发的程序员,基本是是web架构,对数据库增删查改数据,然后把数据展...

weixin_35572076的博客 284

18006.STM32通过SPI读取LAN9253数据

【代码】18006.STM32通过SPI读取LAN9253数据。

写给自己的笔记 556

比心app源码,快速排序法

比心app源码,快速排序法实现的相关代码 void qsort(int * arr,int begin,int end) { if(begin<end) { int temp=arr[begin]; int i=begin; int j=end; while(i<j) { while(i<j&&arr[j]>temp) --j; arr[i]=arr[j]; while(i<j&&arr[i]&l

云豹网络科技 552

撸毛笔记-电信营业厅 v5.03

电信营业厅 v5.03签到和完成部分金豆任务, 喂宠物7天,15天,28天连签抽奖, 宠物等级权益兑换自己设置电信的服务密码, 把 手机号#服务密码 填到变量里:每天运行一两次const $ = new Env("电信营业厅");

xiaoshun007的专栏 4497

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

python 快速排序法

递归实现快速排序法:def quitsort(arr): if len(arr)<=1: return arr pivot=arr[len(arr)/2] left=[x for x in arr if x<pivot] middle=[x for x in arr if x==pivot] right=[x for x in arr if x

797

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

【初探数据结构】快速排序的四种实现方式(Hoare,挖坑,前后指针,非递归)

快速排序是一种高效的分治排序算法,核心思想是通过选定基准元素将数组划分为两部分,递归排序子数组。Hoare法挖坑法前后指针法及非递归实现,并分析其优缺点。快速排序时间复杂度ON∗logNO(N*logN)ON∗logNHoare法适合教学和理解分治思想。挖坑法在减少交换次数时表现优异。前后指针法代码简洁,适合扩展。非递归实现解决了递归栈溢出的问题,适合工程应用。gitee源码理解每种方法的核心逻辑和细节,才能在实际应用中灵活选择最优方案。

Surplus886的博客 1046

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

Arduino 基础编程算法-快速排序法

Arduino 基础编程算法-快速排序法

weixin_44105105的博客 449

C语言中快速排序法(从小到大)实现过程详细分析

快速排序法:实际上是对冒泡排序法的一种改进。 算法:是描述求解问题方法的操作步骤集合。 快速排序法这一算法的基本思想是:首先设定一个分界值(一般是数组中的起始元素值),通过该分界值将数组的元素值分成左右两部分(这里是把数组元素值从小到大排序,所以将大于分界值的数组元素值分到右边,小于分界值的数组元素值分到左边)。同理,分别对左右两部分的数组元素值重复上述步骤:设定起始元素值为分界值,将大于分界值的数组元素值分到右边,小于分界值的数组元素值分到左边,最后实现数组元素值从小到大排序。上述过程实际上就是算法的递归

热爱学习 4512

php 快速排序算法,PHP两种快速排序算法实例

虽然在PHP这样的web应用开发中,我们不是太强调排序的重要性,因为PHP自身已经带了例如sort()等这样强大的排序函数,但是在一些重要的场合,例如某些高并发的场合,我想排序算法的影响已经不能忽略。所以在此介绍递归排序和迭代排序。递归法:/*** 递归法实现的快速排序*/function quicksort($seq){$k = $seq[0];$x = array();$y = array()...

weixin_33628144的博客 120

2016蓝桥杯快速排序

排序在各种场合经常被用到。 快速排序是十分常用的高效率的算法。 其思想是:先选一个“标尺”, 用它把整个队列过一遍筛子, 以保证:其左边的元素都不大于它,其右边的元素都不小于它。 这样,排序问题就被分割为两个子区间。 再分别对子区间排序就可以了。 下面的代码是一种实现,请分析并填写划线部分缺少的代码。 #include <stdio.h> void swap(int a[], int i, int j) { int t = a[i]; a[i] = a[j]; a[j] = t; }..

m0_60300573的博客 229

【练习3】快速排序法解决字母易位词问题

编写一个函数来判断。

Haytham233的博客 175

java 算法基础之五快速排序法

快速排序法与一般的冒泡排序法差不多,区别可能就是冒泡会不断的交换,而快速排序法先找到最小的那个值,然后把这个最小值放在数组的最前面,游标往下走, 举个例子: 原数组:4,5,1,7,6 第一趟:1,5,4,7,6 第二趟:1,4,5,7,6 第三趟:1,4,5,6,7 这个原理比较简单。 代码由下: class Select { public void select

676

快速排序法(三)

说明 之前说过轴的选择是快速排序法的效率关键之一,在这边的快速排序法的轴选择方式更加快了 快速排序法的效率,它是来自演算法名书 Introduction to Algorithms之中。 解法 先说明这个快速排序法的概念,它以最右边的值 s作比较的标准,将整个数列分为三个部份, 一个是小于s的部份,一个是大于s的部份,一个是未处理的部份,如下所示: 小于S 大于S 未处理 ...

webdev 118
上一篇: 日期操作积累
下一篇: PHP 时间戳和日期相互转换
dichen3237
博客等级 码龄11年 0粉丝 0原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值