算法学习—排序

news2024/9/24 9:26:22

排序算法

一、选择排序

1.算法简介

选择排序是一个简单直观的排序方法,它的工作原理很简单,首先从未排序序列中找到最大的元素,放到已排序序列的末尾,重复上述步骤,直到所有元素排序完毕。

2.算法描述

1)假设未排序序列的第一个是最大值,记下该元素的位置,从前往后比较
2)若某个元素比该元素大,覆盖之前的位置
3)重复第二个步骤,直到找到未排序的末尾
4)将未排序元素的第一个元素和最大元素交换位置
5)重复前面几个步骤,直到所有元素都已经排序。

3.算法分析

选择排序的交换操作次数最好情况已经有序为0次,最坏情况逆序n-1次,因此交换操作次数位于0(n-1)次之间;比较操作次数(n-1+…+2+1+0)为n(n-1)/2次;交换元素赋值操作为3次,逆序需要n-1趟交换,因此,赋值操作位于03(n-1)次之间。由于需要交换位置,所以肯定是不稳定的。

时间复杂度均为o(n^2) 空间复杂度为o(1) 不稳定

4.代码实现

//选择排序
function selsetSort(arr){
	var len = arr.length;
	for(var i=0;i<len-1;i++){
		for(var j=i+1;j<len;j++){
			if(arr[i] > arr[j]){//寻找最小值
                var temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
			}
		}
	}
	return arr;
}

二、冒泡排序

1.算法简介

列表每两个相邻的数进行比较,如果前面的数比后面的数大,则交换这两个数,一轮排序完成后,则无序区减少一个数,有序区增加一个数。

2.算法描述

1)快速排序的特点就是随机设置一个基准点,比如是数组的第一个元素,然后数组的其他元素就跟这个基准线进行对比,比基准线大的放在左边,比基准线小的放在右边
2)再设置一个基准线,再这样小的放左边,大的放右边,递归。

3.算法分析

平均时间复杂度O(nn) 、最好情况O(n)、最差情况O(nn)

空间复杂度O(1) 稳定

4.代码实现

 function sort(arr){
     let len = arr.length;
     for (let i = 0; i < len - 1 ; i++) {
         // 用来标记在一轮冒泡过程中有无交换过
         let flag = false;
         for (let j = 0; j < len - i; j++) {
             if(arr[j] > arr[j+1]){
                 // 交换两个数
                 let temp = arr[j];
                 arr[j] = arr[j+1];
                 arr[j+1] = temp;
                 flag = true;
             }
         }
         // 如果在一轮冒泡过程中没有交换过,说明此时的列表已经是排序好的了,直接结束循环
         if(!flag){
             return;
         }
     } 
 }
let arr = [2,3,1,4,8,7,9,6];
this.sort(arr;
console.log(arr); 

三、插入排序

1.算法简介

所谓插入排序,就是把最小的(或者最大的),一次次插入到最前面,从而达到排序的效果

2.算法描述

刚开始将整个数组看作一个无序区,每一轮拿无序区的第一数与有序区的数从后往前依次进行比较,遇到更大的数则交换,每一轮排序完成后,有序区增加一个数,无序区减少一个数。

3.算法分析

时间复杂度是O(n*n) 空间复杂度为o(1) 稳定

4.代码实现

function sort(arr){
    let len = arr.length;
    for (let i = 1; i < len; i++) {
        for (let j = i - 1; j >= 0 ; j--) {
            if(arr[j] > arr[j+1]){
                let temp = arr[j+1]
                arr[j+1] = arr[j]
                arr[j] = temp
            }  
        }  
    }
}, 

四、快速排序

1.算法简介

采用“分治”的思想,对于一组数据,选择一个基准元素(base),通常选择第一个或最后一个元素,通过第一轮扫描,比base小的元素都在base左边,比base大的元素都在base右边,再有同样的方法递归排序这两部分,直到序列中所有数据均有序为止。快速排序算法的性能比冒泡、选择排序都要好,和归并排序一样,是一个可以用于实战的算法。

2.算法描述

1)快速排序的特点就是随机设置一个基准点,比如是数组的第一个元素,然后数组的其他元素就跟这个基准线进行对比,比基准线大的放在左边,比基准线小的放在右边
2)再设置一个基准线,再这样小的放左边,大的放右边,递归。

3.算法分析

时间复杂度是O(nlogn) 空间复杂度为o(logn) 不稳定

4.代码实现

 function sort(arr,l,r){
     if(l < r){
         let i = l;
         let j = r;
         let mid = arr[l];
         while(i < j){
             while(arr[j] > mid && i < j){
                 j--;
             }
             arr[i] = arr[j];
             while(arr[i] < mid && i < j){
                 i++;
             }
             arr[j] = arr[i];
         }
         arr[i] = mid
         this.test(arr,l,i-1)
         this.test(arr,i+1,j)
         return arr
     }else{
         return
     }
 }, 
 // 测试数据
let arr = [2,3,1,4,8,7,9,6];
let res = this.sort(arr,0,7);
console.log(res); 

五、归并排序

1.算法简介

使用分而治之的概念对给定的元素列表进行排序。它将问题分解为较小的子问题,直到它们变得足够简单以至可以直接解决为止。

2.算法描述

1)将给定的列表分为两半(如果列表中的元素数为奇数,则使其大致相等)。

2)以相同的方式继续划分子数组,直到只剩下单个元素数组。

3)从单个元素数组开始,合并子数组,以便对每个合并的子数组进行排序。

4)重复第 3 步单元,直到最后得到一个排好序的数组。

3.算法分析

时间复杂度是O(nlogn) 空间复杂度为O(n) 稳定

4.代码实现

function sort(arr){
    if(arr && arr.length > 1){
        const mid = Math.floor(arr.length/2)
        const left = arr.slice(0,mid)
        const right = arr.slice(mid);
        return this.merge(this.sort(left), this.sort(right))
    }
    return arr
},
function merge(leftList, rightList){
    const newList = [];
    const leftLength = leftList && leftList.length;
    const rightLength = rightList && rightList.length;
    let i = 0;
    let j = 0;
    while (i < leftLength && j < rightLength) {
        if (leftList[i] < rightList[j]) {
            newList.push(leftList[i++]);
        } else {
            newList.push(rightList[j++]);
        }
    }
    while (i < leftLength) {
        newList.push(leftList[i++]);
    }
    while (j < rightLength) {
        newList.push(rightList[j++]);
    }
    return newList;
}, 

六、堆排序

1.算法简介

堆是一种特殊的完全二叉树,堆分为大根堆和小根堆,满足任一节点都比其孩子节点大的一个完全二叉树就是大根堆,满足任一节点都比其孩子节点小的一个完全二叉树就是小根堆。

2.算法描述

首先构造一个大根堆(此时整个堆是无序区),然后将堆顶的元素取出放到有序区(也就是数组的最后),然后将堆的最后一个元素(也就是无序区的最后一个元素)放到堆顶,堆就少了一个元素,此时通过一次向下调整重新使堆有序,调整后的堆顶就是整个数组的第二大元素,然后重复之前的操作依次将元素放到有序区,直到堆变空,便可得到排序好的数组。

3.算法分析

时间复杂度是O(nlogn) 空间复杂度为O(1) 不稳定

4.代码实现

function sort(list) {
    if (list && list.length > 1) {
        const len = list.length;
        // 首先构造大根堆,从最后一个不是叶子节点的节点开始遍历,从后往前依次进行向下调整
        for (let i = Math.floor((len-2)/2); i>=0; i--) {
            sift(list, i, len-1);
        }
        // 然后将堆的第一元素与有序区的第一个元素进行交换,此时有序区增加一个,无序区减少一个,再进行一次堆的向下调整,然后重复上述操作,最终使整个数组有序
        for(let i = len-1; i>=0; i--){
            const m = list[0];
            list[0] = list[i];
            list[i] = m;
            sift(list, 0, i-1);
        } 
    }
}

/**
* 堆的向下调整
* 先从根节点开始,如果孩子节点比父节点大,则将该孩子节点赋值给父节点
* 然后指针指向下一层,重复上面的操作,直到找到孩子节点没有比父节点大的节点,终止循环
* 最后将原始的根节点赋值给当前父节点
*/
function sift(li, low, high) {
    const tmp = li[low]; // 缓存根节点
    let i = low; // 当前的父节点,最开始指向根节点
    let j = i*2+1; // 当前的孩子节点,最开始指向根节点的左孩子节点

    while (j <= high) {
        // 如果有右孩子节点且比左孩子节点大,则j指向右孩子节点
        if (j+1 <= high && li[j+1] > li[j]) {
            j++;
        }
        if (li[j] > tmp) {
            li[i] = li[j]; // 将较大的孩子节点赋值给父节点
            i = j; // i指向下一层
            j = i*2 +1;
        } else {
            break; // 如果当前子节点没有比原始根节点大,结束循环
        }
    }

    li[i] = tmp; // 最后将原始的根节点赋值给当前父节点
}

总结

排序算法复杂度总结图.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1285278.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux中项目部署步骤

安装jdk&#xff0c;tomcat 安装步骤 1&#xff0c;将压缩包&#xff0c;拷贝到虚拟机中。 通过工具&#xff0c;将文件直接拖到虚拟机的/home下 2&#xff0c;回到虚拟机中&#xff0c;查看/home下&#xff0c;有两个压缩文件 3&#xff0c;给压缩文件做解压缩操作 tar -z…

分享70个节日PPT,总有一款适合您

分享70个节日PPT&#xff0c;总有一款适合您 70个节日PPT下载链接&#xff1a;https://pan.baidu.com/s/1IRIKuFoGjQJ14OVkeW_mDQ?pwd6666 提取码&#xff1a;6666 Python采集代码下载链接&#xff1a;采集代码.zip - 蓝奏云 学习知识费力气&#xff0c;收集整理更不易…

Nuxt3 使用 pinia 基础

官方文档 一、安装 pnpm add pinia/nuxt二、配置 添加到 nuxt.config.js 中的 modules &#xff08;Nuxt 3&#xff09;或 buildModules &#xff08;Nuxt 2&#xff09;&#xff1a; // Nuxt 2 export default {buildModules: [[pinia/nuxt, { disableVuex: true }]], } /…

MySQL-含json字段表和与不含json字段表查询性能对比

含json字段表和与不含json字段表查询性能对比 说明: EP_USER_PICTURE_INFO_2:不含json字段表 20200729json_test:含有json字段表 其中20200729json_test 标准ID、MANAGER_NO、PHONE_NO 为非json字段 data为json字段 2个表中MANAGER_NO、PHONE_NO都创建了各自的索引 测试…

拼多多电商平台API接口,获取拼多多实时准确数据,获取产品销量、价格,sku图片及sku库存数据演示

拼多多商品详情API接口的作用是让开发者可以获取拼多多平台上特定商品的详细信息&#xff0c;包括商品的标题、价格、图片、规格、参数以及店铺信息等。通过这个接口&#xff0c;开发者可以轻松地获取商品的原始数据&#xff0c;便于进行数据分析、价格比较、爬取等操作。这为电…

python和php语言编写大型爬虫那个更适用 ?

以我多年从事爬虫行业的经验来说&#xff0c;其实python和php两种语言都可以用于编写大型爬虫项目&#xff0c;但是因为Python语言简洁方便&#xff0c;第三方库相比有很多&#xff0c;数据处理能力也很强&#xff0c;所以受到大多数程序员的追捧。 Python和PHP都可以用于编写…

32位旧内核2038溢出time记录

项目中有使用arm32的机器 现在内核动不了 有个使用时间范围显示是2023-2123 int在32bit下的 2038危机诞生了。 下面在svn找到代码 优化了一下 供大家学习哈&#xff0c;废话不多说直接上家伙&#xff1a; 需要的函数自己抄 #pragma once #include <stdio.h> #include …

Java 并发编程面试题——Java 线程间通信方式

目录 1.✨Java 线程间有哪些通信方式&#xff1f;1.1.volatile 和 synchronized 关键字1.2.等待/通知机制1.2.1.概述1.2.2.经典范式 1.3.管道输入/输出流1.4.信号量 2.Thread.join() 有什么作用&#xff1f;它的使用场景是什么&#xff1f;3.Java 中需要主线程等待子线程执行完…

家用打印机品牌多,种类杂,那么如何挑选最适合的家用打印机

在购买最好的家用打印机时&#xff0c;你可能会寻找足够多功能的打印机来满足每个人的需求。你的家人可能需要复印文件签字&#xff0c;扫描精致的旧照片&#xff0c;或者在接到通知后立即打印长篇文章或报告。良好的扫描功能确保你可以快速高效地将工作数字化&#xff0c;而每…

工程化使用React

安装 首先全局安装 npm install create-react-app -g创建项目 create-react-app proName最基本的一个react工程化创建完成 项目目录

CRM:如何通过客户数据分析获得业务洞察?

客户数据分析&#xff0c;也称客户分析&#xff0c;是收集、组织和分析客户数据&#xff0c;以深入了解客户行为的过程。企业将利用这些数据来制定与营销、产品开发、销售等相关的业务决策。 通过客户分析&#xff0c;你可以做出简单的业务决策&#xff0c;比如找出投资回报率…

基于PaddleSeg开发的人像抠图web api接口

前言 基于PaddleSeg开发的人像抠图web api接口&#xff0c;提取官方代码&#xff0c;适配各种系统&#xff0c;通过api的接口进行访问。 环境要求 1、Python3.7以上 2、源码&#xff08;文章最后下载&#xff09; 源码结构 测试module.py中添加如下代码&#xff1a; if __na…

城市内涝监测如何防治

洪涝灾害是我国历史上主要自然灾害之一&#xff0c;由于我国大部分地区受季风气候影响和降水季节性分配和空间分布不平衡等因素&#xff0c;一些城市洪涝灾害易发多发&#xff0c;危及城市居民的生命财产安全&#xff0c;也影响城市安全运行和可持续发展。因此&#xff0c;城市…

SQL Sever 基础知识 - 数据筛选(1)

SQL Sever 基础知识 - 四、数据筛选 四、筛选数据第1节 DISTINCT - 去除重复值1.1 SELECT DISTINCT 子句简介1.2 SELECT DISTINCT 示例1.2.1 DISTINCT 一列示例1.2.2 DISTINCT 多列示例 1.2.3 DISTINCT 具有 null 值示例1.2.4 DISTINCT 与 GROUP BY 对比 第2节 WHERE - 过滤查询…

easyexcel的@NumberFormat源码解析

debug了一天&#xff0c;关键源码如下&#xff1a; com.alibaba.excel.write.executor.AbstractExcelWriteExecutor#converterAndSet 由于 NumberFormat 注解对应的字段肯定是 BigDecimal &#xff0c;所以肯定会走这一步 然后进行赋值&#xff0c;然后再之前给cell设置好了格…

linux部署前端页面(实战)

Linux基本命令&#xff08;学习笔记&#xff09;零基础入门linux系统运维_linux find exec rm_Z_Xshan的博客-CSDN博客 如果linux不熟可以看我之前写的入门教程 感谢支持&#xff01;&#xff01; 一、服务器 这里去购买云服务器&#xff0c;如果是练习可以用虚拟机&#xff…

Sequential Modeling Enables Scalable Learning for Large Vision Models

目录 一、论文速读 1.1 摘要 1.2 论文概要总结 二、论文精度 2.1 论文试图解决什么问题&#xff1f; 2.2 论文中提到的解决方案之关键是什么&#xff1f; 2.3 论文提出的架构和损失函数是什么&#xff1f; 2.4 用于定量评估的数据集是什么&#xff1f;代码有没有开源&a…

【设计模式】单例模式代码设计

目录 单例模式简介饿汉单例模式懒汉单例模式线程安全的懒汉单例模式 橙色 详细可参考该篇文章&#xff1a;C设计模式 - 单例模式 单例模式简介 单例模式指的是&#xff0c;无论怎么获取&#xff0c;永远只能得到该类类型的唯一一个实例对象&#xff0c;那么设计一个单例就必须…

麒麟inux无法打印pdf文档的Bug解决

笔者手里有一批国产linu系统&#xff0c;目前开始用在日常的工作生产环境中&#xff0c;我这个老程序猿勉为其难的充当运维的或网管的角色。 国产linu系统常见的为麒麟Linux&#xff0c;统信UOS等&#xff0c;基本都是基于debian再开发的linux。 bug描述&#xff1a; 打印机…