当前位置: 首页 > news >正文

排序算法学习笔记

排序算法

稳定性:如果a原本在b前面且a=b,排序之后a仍然在b前面,则稳定;如果排序之后a可能会在b后,则不稳定。

非线性时间比较类排序

通过比较来决定元素间的相对次序,时间复杂度不能突破O(nlogn)。

交换排序

冒泡排序(bubble sort)

一次比较两个元素,如果顺序不对则交换过来。

时间复杂度:O(n^2),优化后最好时间复杂度可为O(n)。
空间复杂度:O(1)。
稳定性:稳定。

示例代码:

//普通
function srotfunction($a){
    $count = count($a);
    for($i=$count-1; $i>0; $i--){
        for($j=0;$j<$i;$j++){
            if($a[$j] > $a[$j+1]){
                $tmp = $a[$j];
                $a[$j] = $a[$j+1];
                $a[$j+1] = $tmp;
            }
        }
        
    }
    return $a;
}
//优化后,用 didswap 标记是否有交换动作。如果本身有序,则执行一次。
function srotfunction($a){
    boolean $didswap;
    
    $count = count($a);
    for($i=$count-1; $i>0; $i--){
        $didswap = false;
        for($j=0;$j<$i;$j++){
            if($a[$j] > $a[$j+1]){
                $tmp = $a[$j];
                $a[$j] = $a[$j+1];
                $a[$j+1] = $tmp;
                
                $didswap = true;
            }
        }
        
        if($didswap == false){
            break;
        }
    }
    return $a;
}

快速排序(quick sort)

通过基准元素,分为两组子串,继续对字段分组,以达到整个序列有序。基准元素一般选择第一个元素或最后一个元素。

时间复杂度:O(nlogn)。
空间复杂度:O(nlogn)。
稳定性:不稳定。

代码示例:

function partition(&$a, $low, $high){
    $privotKey = $a[$low];
    
    while($low<$high){
        //大于的部分
        while($low<$high && $a[$high]>$privotKey){
            --$high;
        }
        swap($a, $low, $high);
        while($low<$high && $a[$low]<$privotKey){
            ++$low;
        }
        swap($a, $low, $high);
    }
    
    return $low;
}

function quicksort(&$a, $low, $high){
    if($low < $high){
        $privotloc = partition($a, $low, $high);
        quicksort($a, $low, $privotloc-1);
        quicksort($a, $privotloc+1, $high);
    }
}

$b = quicksort($a, 0, count($a)-1);

插入排序

简单插入排序(insertion sort)

构建有序序列,对未排序单元,在已排序序列中从后向前扫描,找到相应位置并插入。

时间复杂度:O(n^2),已有序只比较一次,复杂度为O(n)。
空间复杂度:O(1)。
稳定性:稳定。

代码示例:

function srotfunction($a){
    $len = count($a);
    
    for($i=1; $i<$len; $i++){
        $current = $a[$i];
        $preIndex = $i - 1;

        while($preIndex >=0 && $a[$preIndex] > $current){
            $a[$preIndex+1] = $a[$preIndex];
            $preIndex--;
        }
        
        $a[$preIndex + 1] = $current;
    }
    
    return $a;
}

希尔排序(shell sort)

把数据按下标增量分为多个分组,每组内用插入排序。希尔增量序列{n/2, (n/2)/2, ..., 1}。

时间复杂度:O(n^2)。一些优化的增量序列可以为O(n^3/2)。已经有序的为O(n)。
空间复杂度:O(1)。
稳定性:不稳定。

代码示例:

function srotfunction($a){
    $len = count($a);
    $gap = intval($len / 2);

    for(;$gap>0;$gap=intval($gap/2)){
        for($i=$gap;$i<$len;$i++){
            $j = $i;
            $tmp = $a[$i];

            if($a[$j] < $a[$j-$gap]){
                while($j-$gap>=0 && $a[$j-$gap]>$tmp){
                    $a[$j] = $a[$j-$gap];
                    $j-=$gap;
                }
                $a[$j] = $tmp;
            }
        }
    }
    
    return $a;
}

选择排序

简单选择排序(selection sort)

从未排序字段中找到最小(最大)的元素,放入已排序字段中。

时间复杂度:O(n^2)。
空间复杂度:O(1)。

代码示例:

function srotfunction($a){
    $len = count($a);
    
    for($i=0; $i<$len-1; $i++){
        $min = $i;
        for($j=$i+1; $j<$len; $j++){
            if( $a[$min] > $a[$j]){
                $min = $j;
            }
        }
        
        if($min != $i){
            $tmp = $a[$min];
            $a[$min] = $a[$i];
            $a[$i] = $tmp;
        }
    }
    
    return $a;
}

堆排序(heap sort)

利用堆的数据结构,反复调整结构以使其满足堆定义。
堆:完全二叉树,每个节点的值都大于或等于其左右孩子节点的值(大顶堆),同理小顶堆。

时间复杂度:O(nlogn)。
空间复杂度:O(1)。

基本思路:

  1. 将无序序列构造为一个堆(大顶堆-升序,小顶堆-降序);
  2. 将堆顶元素与末尾元素交换,使最大(最小)元素到数组末尾;
  3. 重新调整结构,使其满足堆定义;
  4. 继续交换堆顶元素与当前末尾元素,反复调整交换,使序列有序。

归并排序(merge sort)

分治法,将已有有序子序列合并获得有序序列。二路归并排序、多路归并排序。

时间复杂度:O(nlogn)。
空间复杂度:O(n)。
稳定性:稳定。

代码示例:

function mergeSort(arr) {  // 采用自上而下的递归方法
    var len = arr.length;
    if (len < 2) {
        return arr;
    }
    var middle = Math.floor(len / 2),
        left = arr.slice(0, middle),
        right = arr.slice(middle);
    return merge(mergeSort(left), mergeSort(right));
}
 
function merge(left, right) {
    var result = [];
 
    while (left.length>0 && right.length>0) {
        if (left[0] <= right[0]) {
            result.push(left.shift());
        } else {
            result.push(right.shift());
        }
    }
 
    while (left.length)
        result.push(left.shift());
 
    while (right.length)
        result.push(right.shift());
 
    return result;
}

线性时间非比较类排序

不通过比较来决定次序,可以以线性时间运行。

计数排序(counting sort)

将输入的数据值转化为键,存储在额外的数组空间中。要求输入的数据必须是有确定范围的整数,k不是很大且序列比较集中时。

时间复杂度:O(n+k) //输入元素是n个0~k之间的整数
空间复杂度:O(n+k)
稳定性:稳定

算法描述:

  1. 找到数组中最大、最小的值,构建新数组c[min, max];
  2. 统计数组中值为i的元素,放入c[i],并累加次数;
  3. 统计完后,将c中元素根据i和值放入新数组。

桶排序(bucket sort)

利用函数的映射关系,计数排序的升级版。

算法描述:

  1. 假设数据服从均匀分布,将数据分到有限数量的桶里;
  2. 对每个桶分别排序(使用其他排序算法或者桶排序);
  3. 将非空桶数据拼接起来。

基数排序(radix sort)

先按低位优先级排序、收集,再按高位优先级排序、收集,以此类推。

算法复杂度图表

图片描述

相关资料

十大经典排序算法(动图演示)

相关文章:

  • LDAP落地实战(一):OpenLDAP部署及管理维护
  • react-redux: async promise
  • Esper——内存计算、事件驱动、SQL支持
  • 梯度下降,牛顿法 ,高斯牛顿法
  • 小程序实践(八):验证码倒计时功能
  • CSS 提示工具(Tooltip)
  • 开放平台下从事开发工作的苦水
  • BigDecimal的用法详解(保留两位小数,四舍五入,数字格式化,科学计数法转数字,数字里的逗号处理)...
  • 分发系统介绍、 expect脚本远程登录、远程执行命令、传递参数
  • 欧几里得扩展算法扩展欧几里得
  • Spring Boot 2.0 整合 ES 5 文章内容搜索实战
  • HyperLedger Fabric ca正式环境部署
  • mysql-ubuntu14.04彻底卸载mysql
  • 检测对象或数组
  • Python--作业2--对员工信息文件,实现增删改查操作
  • 【comparator, comparable】小总结
  • ES6语法详解(一)
  • SpringCloud集成分布式事务LCN (一)
  • Vue 2.3、2.4 知识点小结
  • 分享一个自己写的基于canvas的原生js图片爆炸插件
  • 前端技术周刊 2019-02-11 Serverless
  • 如何正确配置 Ubuntu 14.04 服务器?
  • 仓管云——企业云erp功能有哪些?
  • ​ArcGIS Pro 如何批量删除字段
  • ​html.parser --- 简单的 HTML 和 XHTML 解析器​
  • # C++之functional库用法整理
  • #微信小程序:微信小程序常见的配置传旨
  • ()、[]、{}、(())、[[]]等各种括号的使用
  • (4)Elastix图像配准:3D图像
  • (6)STL算法之转换
  • (利用IDEA+Maven)定制属于自己的jar包
  • (没学懂,待填坑)【动态规划】数位动态规划
  • (免费分享)基于springboot,vue疗养中心管理系统
  • (小白学Java)Java简介和基本配置
  • (一)80c52学习之旅-起始篇
  • (转载)Google Chrome调试JS
  • .libPaths()设置包加载目录
  • .NET CF命令行调试器MDbg入门(一)
  • .net core 调用c dll_用C++生成一个简单的DLL文件VS2008
  • .net core 依赖注入的基本用发
  • .net refrector
  • .Net Remoting(分离服务程序实现) - Part.3
  • .NET 自定义中间件 判断是否存在 AllowAnonymousAttribute 特性 来判断是否需要身份验证
  • .net开源工作流引擎ccflow表单数据返回值Pop分组模式和表格模式对比
  • .NET实现之(自动更新)
  • @ConfigurationProperties注解对数据的自动封装
  • @DateTimeFormat 和 @JsonFormat 注解详解
  • @拔赤:Web前端开发十日谈
  • []C/C++读取串口接收到的数据程序
  • [20170705]lsnrctl status LISTENER_SCAN1
  • [Android] Amazon 的 android 音视频开发文档
  • [BJDCTF2020]The mystery of ip1
  • [ExtJS5学习笔记]第三十节 sencha extjs 5表格gridpanel分组汇总
  • [Geek Challenge 2023] web题解
  • [go] 策略模式