内排序算法
排序算法是面试中常见的问题,不同算法的时间复杂度、稳定性和适用场景各不相同。按照数据量和存储方式可以将排序算法分为 内排序(Internal Sorting)和 外排序(External Sorting)。
内排序是指对所有待排序的数据都可以一次性加载到内存中进行排序。这意味着所有的数据都可以直接在计算机的内存中操作,无需借助外部存储设备(如硬盘)。内排序算法的设计可以更加灵活,因为内存操作速度远远高于磁盘操作速度。常见的内排序算法包括快速排序、归并排序、插入排序、冒泡排序等。
外排序是指对大量数据进行排序时,由于数据无法一次性加载到内存中,需要借助外部存储设备进行排序。通常在外排序中,数据会被分成若干个小块,每次只处理其中一部分数据,然后将部分排序好的数据存储回外部存储设备,再进行合并等操作。外排序算法需要考虑数据的分块、读写外部存储的效率,以及合并有序数据等问题。常见的外排序算法有多路归并排序、置换选择排序等。
本文介绍的都是常见的内排序算法:插入排序、冒泡排序、选择排序、希尔排序、归并排序、快速排序、堆排序、桶排序。
目录
- 1. 插入排序
- 2. 冒泡排序
- 3. 选择排序
- 4. 希尔排序
- 5. 归并排序
- 6. 快速排序
- 7. 堆排序
- 8. 桶排序
1. 插入排序
插入排序的核心是将待排序的元素逐个插入到已经排好序的序列中,以构建有序的输出序列:
void inssort(int A[],int n){for(int i=1;i<n;i++){for(int j=i;j>0;j--){if(A[j]<A[j-1]){ //A[j]<A[j-1](此处小于即排在前面)swap(A,j,j-1);}else{break; //A[j]已达到正确位置(时间优化)}}}
}
插入排序的平均时间复杂度为 O(n2),最好情况为 O(n),最坏情况为 O(n2),适用于小规模的数据集或者已经基本有序的数据。插入排序的空间复杂度为 O(1),是一种稳定排序算法。
2. 冒泡排序
冒泡排序的核心思想是通过比较相邻的元素并交换位置,逐渐将最小的元素 “冒泡” 到正确的位置。冒泡排序的过程类似于冒泡泡沫在水中升起的过程,较大的元素会逐渐向序列的开头 “冒泡”:
void bubsort(int A[],int n){for(int i=0;i<n-1;i++){for(int j=n-1;j>i;j--){if(A[j]<A[j-1]){swap(A,j,j-1);}}}
}
冒泡排序的平均时间复杂度为 O(n2),最好情况和最坏情况都为 O(n2)。冒泡排序的空间复杂度为 O(1),是一种稳定排序算法。
3. 选择排序
选择排序的核心思想是在未排序序列中选择最小的元素,然后将它与未排序序列的起始位置交换,使得已排序序列逐步增长:
void selsort(int A[],int n){for(int i=0;i<n-1;i++){int index=i;for(int j=n-1;j>i;j--){if(A[j]<A[index]){index=j;}}swap(A,i,index);}
}
选择排序的平均时间复杂度为 O(n2),最好情况和最坏情况都为 O(n2)。选择排序的空间复杂度为 O(1),是一种稳定排序算法。
4. 希尔排序
希尔排序利用了插入排序最佳时间代价特性,在不相邻的记录之间进行交换和比较。核心思想是将整个序列分成多个较小的子序列来逐步减少序列的无序度,从而在最后一步进行一次插入排序,达到提高排序速度的效果。过程如图:
void inssort2(int A[],int n,int incr){ //n为传入数组长度,incr为数组内元素间隔for(int i=incr;i<n;i+=incr){ //incr相当于第1位元素,+incr相当于间隔for(int j=i;(j>=incr)&&(A[j]<A[j-incr]);j-=incr){int tmp=A[j];A[j]=A[j-incr];A[j-incr]=tmp;cnt1++;}}
}
void shellsort(int A[],int n){for(int i=n/2;i>2;i/=2){ //i表示组数或者间隔for(int j=0;j<i;j++){ //j表示有i组数据时从0到i遍历inssort2(&A[j],n-j,i); //对第j组数据进行插入排序(起始位置,长度,间隔)//第j组数据在A中下标:j,j+i,j+2i...用inssort2中传入参数表示为:&A[j],&A[j]+i,&A[j]+2i...}}inssort2(A,n,1); //对整个数组插入排序
}
希尔排序在现实中没有对应的直观解释,也无法证明其时间复杂度,一般认为平均时间复杂度为 O(n1.5),最好情况为 O(nlogn),最坏情况为 O(n2)。希尔排序的空间复杂度为 O(1),是一种不稳定排序算法。
5. 归并排序
归并排序的核心思想是 “二分+合并”,即将一个未排序的数组分割成两个子数组,递归地对这两个子数组排好序后再合并为一整个有序的数组:
void mergesort(int A[],int tmp[],int left,int right){ //left表示A[0]下标,right表示A[n-1]下标if(left==right) return;int mid=(left+right)/2;mergesort(A,tmp,left,mid); //向下递归,二分集合并排序mergesort(A,tmp,mid+1,right);for(int i=left;i<=right;i++){tmp[i]=A[i];}int i1=left,i2=mid+1; //i1,i2表示两个待合并数组(各自都已排序)首个未排序元素下标for(int curr=left;curr<=right;curr++){if(curr==mid+1){ //left数组已完成合并A[curr]=tmp[i2++];}else if(i2>right){ //right数组已完成合并A[curr]=tmp[i1++];}else if(tmp[i1]<tmp[i2]){A[curr]=tmp[i1++];}else{A[curr]=tmp[i2++];}}
}
归并排序的平均时间复杂度为 O(nlogn),最好情况和最坏情况也都为 O(nlogn)。归并排序的空间复杂度为 O(n),是一种稳定排序算法。
6. 快速排序
快速排序的核心思想是选择一个轴值 pivot,将数组分为小于轴值的部分和大于轴值的部分,然后递归地对这两部分进行排序。轴值的选择会影响算法的效率,一般选取数组的中间点作为轴值。为了设计方便,会将轴值置于数组末端,待排好序后再移动到合适位置:
//partition函数将数组的l+1~r-1划分为两个以轴值为分界的部分,并返回轴值的下标(实际上该位元素与最后一位交换后才是真正的轴值下标)
int partition(int A[],int l,int r,int& pivot){ //l,r为A[]的左右范围,pivot为轴值do{while(A[++l]<pivot); //跳过满足小于轴值的元素,终止在大于轴值的地方while((l<r)&&(A[--r]>pivot));int tmp=A[r];A[r]=A[l];A[l]=tmp;}while(l<r);return l;
}void qsort(int A[],int i,int j){if(i>=j) return;int pivotindex=(i+j)/2; //选取轴值int pivot=A[pivotindex];A[pivotindex]=A[j]; //将轴值与末尾元素互换A[j]=pivot;pivotindex=partition(A,i-1,j,A[j]); //将l+1~r-1按轴值分部,并返回待与轴值交换元素下标pivot=A[j]; //轴值还在末尾等待交换A[j]=A[pivotindex];A[pivotindex]=pivot;qsort(A,i,pivotindex-1);qsort(A,pivotindex+1,j);
}
快速排序是迄今为止所有内排序算法中在平均情况下最快的一种,当每个轴值都把数组分成相等的两个部分时,整个算法的时间代价是 Θ \Theta Θ(nlogn)。快速排序的平均时间复杂度为 O(nlogn),最好情况为 O(nlogn),最坏情况为 O(n2)。快速排序的空间复杂度为 O(logn),是一种不稳定排序算法。
7. 堆排序
堆排序是基于堆数据结构的排序算法,它利用最小堆的性质来实现对数组的排序:
class heap{
private:int* Heap;int maxsize;int n;void siftdown(int pos){while(!isLeaf(pos)){int j=leftchild(pos); //下面j表示的是lc和rc中较小值的下标int rc=rightchild(pos);if((rc<n)&&(Heap[rc]<Heap[j])){j=rc;}if(Heap[pos]<Heap[j]){return;}int tmp=Heap[pos];Heap[pos]=Heap[j];Heap[j]=tmp;pos=j;}}
public:heap(int* h,int num,int max){Heap=h;n=num;maxsize=max;buildHeap();}int size(){return n;}bool isLeaf(int pos){return (pos>=n/2)&&(pos<n);}int leftchild(int pos){return 2*pos+1;}int rightchild(int pos){return 2*pos+2;}int parent(int pos){return (pos-1)/2;}void buildHeap(){for(int i=n/2-1;i>=0;i--){siftdown(i);}}void insert(const int& it){int curr=n++;Heap[curr]=it;while((curr!=0)&&(Heap[curr]<Heap[parent(curr)])){int tmp=Heap[curr];Heap[curr]=Heap[parent(curr)];Heap[parent(curr)]=tmp;curr=parent(curr);}}int removefirst(){n--;int tmp=Heap[0];Heap[0]=Heap[n];Heap[n]=tmp;if(n!=0){siftdown(0);}return Heap[n];}int remove(int pos){if(pos==(n-1)){n--;}else{n--;int tmp=Heap[pos];Heap[pos]=Heap[n];Heap[n]=tmp;while((pos!=0)&&(Heap[pos]<Heap[parent(pos)])){int tmp=Heap[pos];Heap[pos]=Heap[parent(pos)];Heap[parent(pos)]=tmp;pos=parent(pos);}if(n!=0){siftdown(pos);}}return Heap[n];}
};
void heapsort(int A[],int n){int minval;heap H(A,n,n);for(int i=0;i<n;i++){minval=H.removefirst();}
}
堆排序的平均时间复杂度为 O(nlogn),最好情况和最坏情况也都为 O(nlogn),但比快速排序要慢一个常数因子。堆排序在实际使用时适用于查找第 k 大小的元素,或者用于外排序。堆排序的空间复杂度为 O(1),是一种不稳定排序算法。
8. 桶排序
桶排序的核心思想是将数组按数值范围放入若干个桶,每个桶对应一定范围的数据,然后对每个桶中的数据使用其他排序算法或递归方式进行排序,最后将所有桶中的数据按顺序合并得到排序结果:
void inssort(int A[],int n){for(int i=1;i<n;i++){for(int j=i;j>0;j--){if(A[j]<A[j-1]){int tmp=A[j];A[j]=A[j-1];A[j-1]=tmp;}else{break;}}}
}void bucketSort(int A[],int n,int numBuckets){//创建桶int buckets[numBuckets][n]; //二维数组,每行表示一个桶int bucketSizes[numBuckets]; //每个桶中元素的数量//初始化桶的大小for(int i=0;i<numBuckets;i++){bucketSizes[i]=0;}//确定数组元素范围int maxA=-999,minA=999;for(int i=0;i<n;i++){if(A[i]>maxA) maxA=A[i];if(A[i]<minA) minA=A[i];} //将元素放入桶中for(int i=0;i<n;i++){int bucketGap=ceil((maxA-minA)/(float)numBuckets);int bucketIndex=(A[i]-minA)/bucketGap;buckets[bucketIndex][bucketSizes[bucketIndex]++]=A[i];}//对每个桶中的元素进行插入排序for(int i=0;i<numBuckets;i++){inssort(buckets[i],bucketSizes[i]);}// 合并桶中的元素int index=0;for(int i=0;i<numBuckets;i++){for(int j=0;j<bucketSizes[i];j++){A[index++]=buckets[i][j];}}
}
桶排序的平均时间复杂度为 O(n2),最好情况和最坏情况也都为 O(n2),但比插入排序要快一个常数因子。桶排序适用于在已知输入数据的范围内进行排序,若数据分布不均匀也会影响效率。桶排序的空间复杂度为 O(n2),是一种稳定排序算法。
相关文章:

内排序算法
排序算法是面试中常见的问题,不同算法的时间复杂度、稳定性和适用场景各不相同。按照数据量和存储方式可以将排序算法分为 内排序(Internal Sorting)和 外排序(External Sorting)。 内排序是指对所有待排序的数据都可…...
options.html 页面设计成聊天框,左侧是功能列表,右侧是根据左侧的功能切换成不同的内容。--chatGpt
gpt: 要将 options.html 页面设计成一个聊天框式的界面,其中左侧是功能列表,右侧根据左侧的功能切换成不同的内容,你可以按照以下步骤进行设计和实现: 1. 首先,创建 options.html 文件,并在其中定义基本的…...

排序算法-选择排序法(SelectionSort)
排序算法-选择排序法(SelectionSort) 1、说明 选择排序法也是枚举法的应用,就是反复从未排序的数列中取出最小的元素,加入另一个数列中,最后的结果即为已排序的数列。选择排序法可使用两种方式排序,即在所…...

Java-集合框架
文章目录 摘要CollectionCollection集合遍历Iterator迭代器增强for循环 排序 ListArrayListLinkedListVector SetHashSet Map小结 摘要 Java的集合框架提供了一组用于存储、管理和操作数据的类和接口。这个框架提供了各种数据结构,如列表、集合、队列和映射&#x…...

联想携中国移动打造车路协同方案 助力重庆实现32类车联网场景
10月11日,联想集团在中国移动全球合作伙伴大会上首次分享了与中国移动等合作伙伴共同打造的5G车路协同案例——重庆两江协同创新区车路协同应用。联想利用基于5G智能算力技术,在总里程55公里路段实现了32类车联网场景。 据了解,重庆两江协同创…...

Rust入门基础
文章目录 Rust相关介绍为什么要用Rust?Rust的用户和案例 开发环境准备安装Rust更新与卸载Rust开发工具 Hello World程序编写Rust程序编译与运行Rust程序 Cargo工具Cargo创建项目Cargo构建项目Cargo构建并运行项目Cargo检查项目Cargo为发布构建项目 Rust相关介绍 为…...

民族民俗景区3d智慧旅游系统提升游客旅游体验和质量
随着科技的不断发展,传统的旅游方式正在逐渐被新的技术和系统所取代。网上3D沉浸式旅游体验凭借其身临其境的沉浸式体验优势,正成为旅游业的新宠。 网上3D沉浸式旅游体验是将旅游景区、度假区、休闲街区、科博馆等场所空间,利用VR全景制作、w…...

Webpack 解决:Error: error:0308010C:digital envelope routines::unsupported 的问题
1、问题描述: 其一、报错为: Error: error:0308010C:digital envelope routines::unsupported 中文为: 错误:错误:0308010C:数字信封例程::不支持 其二、问题描述为: 在项目打包的时候 np…...
JAVA操作Json的ObjectMapper类
JAVA操作Json的ObjectMapper类 市面上用于在 Java 中解析 Json 的第三方库,随便一搜不下几十种,其中的佼佼者有 Google 的 Gson以及本文的 jackson。 三者不相伯仲,随着掌握一个都能满足项目中的 json 解析操作,因为 Spring Boot…...
Docker--harbor
一,registry registry是私有仓库的核心,只有字符终端。 二,registry部署 #首先下载 registry 镜像 docker pull registry#在 daemon.json 文件中添加私有镜像仓库地址 vim /etc/docker/daemon.json {"insecure-registries": [&q…...

Flink中的时间和窗口
1.Flink的时间和窗口 在传统的批处理系统中,我们可以等到一批数据全部都到齐了之后,对其做相关的计算;但是在实时处理系统中,数据是源源不断的,正常情况下,我们就得来一条处理一条。那么,我们应…...
Ultra-Fast-Lane-Detection 车道线学习资料整理
目录 官方版本 两个优化 数据标注,降低参数量 1 数据标注 2降低参数量...
【Ubuntu】Ubuntu18.04终端卡顿问题
博主您好,我也遇到了类似的问题,但我找到了问题的原因: 在gnome-terminal中,按tab补全是默认开启了“咚咚咚”音效的,在gnome-terminal里把音效关掉就好了,主要是因为按tab时,NVIDIA的视频信号和…...

k8s强制删除pod、svc、namespace(Terminating)
如果名称空间、pod、pv、pvc全部处于“Terminating”状态时,此时的该名称空间下的所有控制器都已经被删除了,之所以出现pod、pvc、pv、ns无法删除,那是因为kubelet 阻塞,有其他的资源在使用该namespace,比如CRD等&…...
froeach迭代删除和List迭代删除问题
场景:我有一个 List<ISSLogMessage> records 数据,需要从里面删除指定内容数据 第一次写成 foreach(var item in records) {if (item.logMessage.Contains("上传通行记录"))records.Remove(item); } 直接报错,因为foreach 是个迭代器 直接移除它的对象会报…...
chromedriver下载地址
ChromeDriver下载地址: 淘宝镜像:https://registry.npmmirror.com/binary.html?pathchromedriver/ 官方镜像:https://sites.google.com/a/chromium.org/chromedriver/downloads在下载页面上,将看到一列Chrome浏览器的版本号和相…...

2ED2410-EM:12v / 24v智能模拟高侧MOSFET栅极驱动器
概述 12v / 24v智能模拟高侧MOSFET栅极驱动器。 特性 PRO-SIL ISO 26262-准备根据ISO 26262:2018条款8-13支持硬件元件评估的集成商。一个通道器件具有两个高侧栅极驱动器输出。3 Ω下拉,50 Ω上拉,用于快速开关开/关。支持背靠背MOSFET拓扑(共漏极和共源)。两个双向高侧模拟…...

什么是Fetch API?与传统的AJAX相比,有什么优势?
聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 欢迎来到前端入门之旅!感兴趣的可以订阅本专栏哦!这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…...
43.241.18.123哪些问题会导致服务器里面时间错误
我们在使用服务器的过程中,有时候可能会发现,服务器里面时间跟标准的时间对不上,那服务器里面时间错误可能由哪些问题引起: 硬件问题:服务器硬件中的时钟或电池可能损坏或失效,导致时间不准确或重置为默认…...

【ElasticSearch】更新es索引生命周期策略,策略何时对索引生效
大家好,我是好学的小师弟,今天和大家讨论下更新es索引生命周期策略后,策略何时对索引生效 结论: 若当前索引已应用策略A(旧),更新完策略A后,新的策略A会立即对原来的已经应用该策略的索引生效;若当前索引…...
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...

抖音增长新引擎:品融电商,一站式全案代运营领跑者
抖音增长新引擎:品融电商,一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中,品牌如何破浪前行?自建团队成本高、效果难控;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...

定时器任务——若依源码分析
分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...

剑指offer20_链表中环的入口节点
链表中环的入口节点 给定一个链表,若其中包含环,则输出环的入口节点。 若其中不包含环,则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...

2021-03-15 iview一些问题
1.iview 在使用tree组件时,发现没有set类的方法,只有get,那么要改变tree值,只能遍历treeData,递归修改treeData的checked,发现无法更改,原因在于check模式下,子元素的勾选状态跟父节…...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...

蓝桥杯3498 01串的熵
问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798, 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...

AI病理诊断七剑下天山,医疗未来触手可及
一、病理诊断困局:刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断",医生需通过显微镜观察组织切片,在细胞迷宫中捕捉癌变信号。某省病理质控报告显示,基层医院误诊率达12%-15%,专家会诊…...
快刀集(1): 一刀斩断视频片头广告
一刀流:用一个简单脚本,秒杀视频片头广告,还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农,平时写代码之余看看电影、补补片,是再正常不过的事。 电影嘛,要沉浸,…...

Windows安装Miniconda
一、下载 https://www.anaconda.com/download/success 二、安装 三、配置镜像源 Anaconda/Miniconda pip 配置清华镜像源_anaconda配置清华源-CSDN博客 四、常用操作命令 Anaconda/Miniconda 基本操作命令_miniconda创建环境命令-CSDN博客...