十个排序算法

目录

冒泡排序(Bubble Sort)

选择排序(Select Sort)

插入排序(InsertSort)

希尔排序(ShellSort)

计数排序(CountSort)

快速排序(QuickSort)

归并排序(Merge Sort)

堆排序(Heap Sort)

桶排序(Bucket Sort)

基数排序(Radix Sort)

总结


冒泡排序(Bubble Sort)

例如:2,32,4,45,6,334,1,33

相邻的两个数之间若前一个数>后一个数,他俩就交换。

第一次交换结果:2 4 32 6 45 1 33 334

第一次交换,最大的一个数就确定了,下次遍历次数就-1。

第二次交换结果:2 4 6 32 1 33 45 334

第二次交换,第二大的数也确定了,下次遍历次数就-2。

以此类推,得出结果:1 2 4 6 32 33 45 334

#include<iostream>
using namespace std;
void Bubblesort(int a[], int len)
{if (a == NULL || len <= 0)return;for (int j = 0; j < len-1; j++) {for (int i = 0; i + 1 < len-j; i++){if (a[i] > a[i + 1])swap(a[i], a[i + 1]);}for (int i = 0; i < len; i++)cout << a[i] << " ";cout<<endl;}
}
int main()
{int arr[] = { 2,32,4,45,6,334,1,33 };Bubblesort(arr, sizeof(arr) / sizeof(arr[0]));for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)cout << arr[i] << " ";return 0;
}

优化:

我们定义一个标记flag,表示最后一次交换的位置,更新i,内层循环需要交换的位置就是0~len-flag-2,外层循环遍历次数也变为flag-1次。

#include<iostream>
using namespace std;
void BubbleSort(int len, int a[])
{int flag;for (int i = 0; i < len - 1; i++){//最后一次交换的位置flag = 0;for (int j = 0; j < len - i - 1; j++){if (a[j] > a[j + 1]){swap(a[j], a[j + 1]);flag = j + 1;}}//没有发生交换if (flag == 0)break;//内层循环更新到上一次最后交换的位置i = len - flag - 1;}
}
int main()
{int a[] = { 5,4,3,2,1 };BubbleSort(sizeof(a) / sizeof(a[0]), a);for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++)cout << a[i] << " ";cout << endl;return 0;
}

选择排序(Select Sort)

每次遍历找到最值(最大值或最小值)放入相应位置。

例如:2,32,4,45,6,334,1,33

找到最小值下标6,和第一个个值交换。

第一次遍历:1 32 4 45 6 334 2 33

第二次遍历从下标1开始找到最小的为下标6和第二个值交换。

第二次遍历:1 2 4 45 6 334 32 33

一此类推,得出结果:1 2 4 6 32 33 45 334

#include<iostream>
using namespace std;
void SelectSort(int len, int a[])
{if (a == NULL || len <= 0)return;int i;int j;int nMin;for (i = 0; i < len-1; i++){nMin = i;for (j = i+1; j < len; j++){if (a[j] < a[nMin])nMin = j;}if (nMin != i)swap(a[i],a[nMin]);}
}
int main()
{int a[] = { 2,32,4,45,6,334,1,33 };SelectSort(sizeof(a) / sizeof(a[0]), a);for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++)cout << a[i] << " ";return 0;
}

插入排序(InsertSort)

适用范围:(1)元素少。(2)每个元素在排序前的位置距其最终排好序的位置不远的时候。

将待排序数据分成两部分,一部分有序,一部分无序,将无序元素依次插入到有序中去,完成排序。

例如: 2,32,4,45,6,334,1,33 

首先有序部分是2,无序部分是32,4,45,6,334,1,33 

用i,j分别记录有序部分位置和无序部分位置。

需要插入n-1次,保存当前需要插入的无序元素。

然后倒序遍历有序元素,如果无序元素比有序元素大那就插入在这个有序元素的下一个位置,如果比它小,那就将有序元素向后移一位继续遍历。循环往复。

2,32,4,45,6,334,1,33 

2,4,32,45,6,334,1,33 

2,4,32,45,6,334,1,33 

2,4,6,32,45,334,1,33

2,4,6,32,45,334,1,33

1,2,4,6,32,45,334,33

1,2,4,6,32,33,45,334

#include<iostream>
using namespace std;
void InsertSort(int len, int a[])
{if (a == NULL || len <= 0)return;int i;int j;int temp;for (i = 1; i < len; i++){j = i - 1;temp = a[i];while (j >= 0 && a[j] > temp){a[j+1] = a[j];j--;}a[j + 1] = temp;}
}
int main()
{int a[] = { 2,32,4,45,6,334,1,33 };InsertSort(sizeof(a) / sizeof(a[0]), a);for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++)cout << a[i] << " ";return 0;
}

希尔排序(ShellSort)

将待排序数据分组,各组之内进行插入排序。(间隔分组 缩小增量)

(1)确定间隔

(2)分组(间隔是几就是分几组)

(3)各组插入排序

例:

按间隔分组后,23,45,43插入排序,1,2插入排序,73,6插入排序,11,8插入排序。

排完序后如下图,继续分组。

按间隔分组后,23,6,43,73,45插入排序,1,8,2,11插入排序。

最后每个元素在排序前的位置距其最终排好序的位置不远的时候也就是插入排序适用的条件。

排完后如下图,继续分组。

最后排完序

计数排序(CountSort)

元素分配密集,且重复出现频率较高,找到最值,统计计数器个数,对每个元素出现次数进行统计。

(1)找到最大值,最小值

(2)创建数组0~max-min

(3)计数

(4)排序:计数值非0,索引+最小值。

​
#include<iostream>
using namespace std;
void CountSort(int len, int a[])
{if (len <= 0 || a == NULL)return;int maxx=a[0];int minn=a[0];for (int i = 1; i < len; i++){maxx = max(maxx, a[i]);minn = min(minn, a[i]);}int* Count = (int*)malloc(sizeof(int) * (maxx - minn + 1));memset(Count, 0, sizeof(int) * (maxx - minn + 1));for (int i = 0; i < len; i++){Count[a[i] - minn]++;}int j = 0;for (int i = 0; i < maxx - minn + 1; i++){while (Count[i] != 0){a[j] = minn + i;Count[i]--;j++;}}free(Count);Count = NULL;for (int i = 0; i < len; i++)cout << a[i] << " ";
}
int main()
{int a[] = { 2,32,4,45,6,334,1,33 };CountSort(sizeof(a) / sizeof(a[0]), a);return 0;
}​

优化:

从计数数组的第二个元素开始,后面每一个都加上前面所有元素之和,数组大小代表了该数据在序列中的位置,所以从后往前输出。

#include<iostream>
using namespace std;
void CountSort(int len, int a[])
{if (len <= 0 || a == NULL)return;int maxx=a[0];int minn=a[0];for (int i = 1; i < len; i++){maxx = max(maxx, a[i]);minn = min(minn, a[i]);}int* Count = (int*)malloc(sizeof(int) * (maxx - minn + 1));memset(Count, 0, sizeof(int) * (maxx - minn + 1));for (int i = 0; i < len; i++){Count[a[i] - minn]++;}for (int i = 1; i < maxx - minn + 1; i++){Count[i] += Count[i - 1];}int* arr = (int*)malloc(len * sizeof(int));for (int i = len - 1; i >=0; i--){arr[Count[a[i] - minn] - 1] = a[i];Count[a[i] - minn]--;}for (int i = 0; i < len; i++)cout << arr[i] << " ";free(Count);Count = NULL;free(arr);arr = NULL;
}
int main()
{int a[] = { 2,2,2,77,77,3,3,4,66,6,4,3,2,1 };CountSort(sizeof(a) / sizeof(a[0]), a);return 0;
}

快速排序(QuickSort)

首先选出标准值,然后(挖坑填补法)从右到左找小于标准值的,放入左侧坑,然后从左到右找大于标准值的放入右侧坑循环,然后两个指向位置相遇了就放入标准值,然后继续找,左:(起始位置,标准值-1),右(标准值+1,结束位置)。

例如:

将左侧9作为标准值,从右向左找小于9的,找到6。

然后将6放入左坑,现在从左往右找比9大的放右坑。

找到45放到右坑,然后再从右向左找小于9的放左坑,找到3。

然后再从左往右找比9大的,发现没有了,标记相遇了。

放入标准值9。

然后在(起始位置,标记值-1) , (标记值+1,结束位置)重复以上过程直到蓝色>=红色标记结束。

#include <stdio.h>
#include <iostream>
#include <math.h>
#include <algorithm>
using namespace std;
int part(int* a, int left, int right)
{int i = left, j = right,k = a[left]; while (i < j){while (i<j ) {if (a[j] < k){a[i] = a[j];i++;break;}j--;}while (i < j){if (a[i] >k){a[j] = a[i];j--;break;}i++;}}a[i] = k;return i;  
}
void Quicksort(int* a, int left, int right)
{if (a == NULL || left >= right)return;int mid;mid = part(a, left, right); Quicksort(a, left, mid - 1);Quicksort(a, mid + 1, right); 
}
int main()
{int a[] = { 9,1,2,45,7,3,6,22,11 };int len = sizeof(a) / sizeof(a[0]);Quicksort(a, 0, len-1);for (int i = 0; i < len; i++){cout << a[i] << " ";}cout << endl;return 0;
}

优化:

选择最右侧的值作为基准元素,在代码中,基准元素前期不需要移动,只需在最后移动就行。

定义nsmall为最后一个小于基准元素的位置。

(1)做标记nsmall。

(2)遍历:从左到右遍历,当前值小于基准值,++nsmall和left是否相等,不相等交换。

(3)标准值放入。

(4)左半部分。

(5)右半部分。

#include <iostream>
using namespace std;
int part(int* a, int left, int right) {int nsmall = left - 1;for (left; left < right; left++){if (a[left] < a[right]){if (++nsmall != left){swap(a[nsmall], a[left]);}}}if (++nsmall != right)swap(a[nsmall], a[right]);return nsmall;
}void Quicksort(int* a, int left, int right) {if (a == NULL || left >= right)return;int mid = part(a, left, right); Quicksort(a, left, mid - 1);    Quicksort(a, mid + 1, right);  
}int main() {int a[] = { 1, 43, 4, 6, 21, 23, 77, 8, 5, 3 };int len = sizeof(a) / sizeof(a[0]);Quicksort(a, 0, len - 1);for (int i = 0; i < len; i++) {cout << a[i] << " ";}cout << endl;return 0;
}

其它优化:

(1)基准值选取:三选一(起始,中间,结束位置选取中数),九选一

(2)基准值聚集(数据重复,基准值选完有重复的把他们聚集)

(3)分割至元素较少(<16)然后插入排序

(4)循环+申请空间(递归要是内存不够会出现异常)

归并排序(Merge Sort)

将多个有序数组进行合并。

例如:

先分成两部分,然后继续往下分。(这里是将两个有序数组合并,多个也一样)

然后从下往上合并,33比12小,所以12,33,2比4小,2,4,然后继续往上合并,2比12小放12前面,4比12小放12前面后面元素都一起拿过来,2,4,12,33,然后其余同理。

步骤:

(1)找中间位置。

(2)分成两部分:左(起始位置,中间位置)右(中间位置+1,结束位置)

(3)合并。

#include<iostream>
using namespace std;
void Merge(int a[], int begin, int end)
{int begin1 = begin;int end1 = begin + (end - begin) / 2;int begin2 = end1 + 1;int end2 = end;int* ptemp = (int*)malloc(sizeof(int)*(end-begin+1));int i=0;while (begin1 <= end1 && begin2 <= end2){if (a[begin2] < a[begin1]){ptemp[i++] = a[begin2++];}else {ptemp[i++] = a[begin1++];}}while (begin1 <= end1){ptemp[i++] = a[begin1++];}while (begin2 <= end2){ptemp[i++] = a[begin2++];}for (int j = 0; j < end - begin + 1; j++){a[begin + j] = ptemp[j];}free(ptemp);ptemp = NULL;
}
void MergeSort(int a[], int begin, int end)
{if (a == NULL || begin >= end)return;int Mid = begin + (end - begin) / 2;MergeSort(a, begin, Mid);MergeSort(a, Mid + 1, end);Merge(a, begin, end);
}
int main()
{int a[] = { 12,33,2,4,8,63,12 };int len = sizeof(a) / sizeof(a[0]);MergeSort(a, 0, len - 1);for (int i = 0; i < len; i++){cout << a[i] << " ";}return 0;
}

堆排序(Heap Sort)

每次找最值,将最值放在相应位置上。

堆:大根堆(大堆),小根堆(小堆)。

(我们这里按大根堆来)首先创建初始堆。

例:

首先我们创建一颗完全二叉树,然后进行调整,父亲节点要比孩子节点大(父亲节点0~n/2-1)

3比1大调整

16比7大调整

12比9大不用调整

16比6大调整

6比8小调整

得到初始堆:16,12,8,3,9,7,6,1

然后开始排序,顶末交换,也就是第一个和最后一个交换

1,16交换变为:1,12,8,3,9,7,6,16

16排好了我们就不看16了,然后我们调整堆顶。

调整完为12,9,8,3,1,7,6,16

然后继续交换调整,重复上面步骤,直到剩一个。

9,6,8,3,1,7,12,16

8,6,7,3,1,9,12,16

7,6,1,3,8,9,12,16。

6,3,1,7,8,9,12,16。

3,1,6,7,8,9,12,16。

结果:1,3,6,7,8,9,12,16。

步骤:

(1)创建初始堆:依次调整各个父亲节点。

(2)顶末交换,调整堆顶,直到只剩下1一个元素。

调整函数:先看孩子个数,然后找孩子里的最大值,最大值比父亲小结束,比父亲大交换。

#include<iostream>
using namespace std;
#define LEFT SwapId*2+1
#define RIGHT SwapId*2+2
void Adjust(int a[], int len, int SwapId)
{int maxx;//因为LEFT一定有for (maxx = LEFT; maxx < len; maxx = LEFT){if (RIGHT < len){if (a[RIGHT] > a[maxx]){maxx = RIGHT;}}if (a[maxx] > a[SwapId]){swap(a[maxx], a[SwapId]);SwapId = maxx;}else {break;}}
}
void HeapSort(int a[], int len)
{if (a == NULL || len <= 0)return;for (int i = len/2 - 1; i >= 0; i--){Adjust(a, len, i);}for (int i = len - 1; i > 0; i--){swap(a[0], a[i]);Adjust(a, i, 0);}
}
int main()
{int a[] = { 12,33,2,4,8,63,23,69,1,12 };int len = sizeof(a) / sizeof(a[0]);HeapSort(a, len);for (int i = 0; i < len; i++){cout << a[i] << " ";}return 0;
}

桶排序(Bucket Sort)

原始:为小数服务的[0,1)相同位数的小数。

延申:整数。

桶与桶之间相互有序。

(1)桶,各桶范围。

(2)各桶内排序(Bubble Sort)。

(3)放回后依次遍历各条链表(哈希)。

(4)释放(先链表,后表头)。

基数排序(Radix Sort)

(LSD从低位优先,MSD高位优先。一般用LSD)

例:

(1)先找最大值。

(2)计算最大值位数。

(3)按位处理:申请组,拆位将数据入组(尾插),表内元素放回原数组,释放。

总结

稳定:排序前后相对位置未发生改变,保证多次排序结果相同,最稳定的就是基数排序,其余的(判断条件>=可能就不稳定了)

名称最优时间复杂度平均时间复杂度最坏时间复杂度空间复杂度稳定性
冒泡排序O(n)O(n^{2})O(n^{2})O(1)稳定
选择排序------O(n^{2})------O(1)不稳定
插入排序O(n)O(n^{2})O(n^{2})O(1)稳定
希尔排序--------------------O(1)不稳定
快速排序O(nlog2^{n})O(nlog2^{n})O(n^{2})O(log2^{n})不稳定
归并排序O(nlog2^{n})O(nlog2^{n})O(nlog2^{n})O(n)稳定
堆排序O(nlog2^{n})O(nlog2^{n})O(nlog2^{n})O(1)不稳定
基数排序O(n*k)O(n*k)O(n*k)O(n+k)稳定

(注:k是最大值位数)

注:

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

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

相关文章

Jenkins 安装部署

1、安装下载 官网地址&#xff1a;Jenkins 下载 war 包 1、前置环境 JDK 环境&#xff08;根据 Jenkins 版本不同&#xff0c;需要的 JDK 版本不同&#xff0c;目前需要 JDK11 的版本来支持&#xff09;Maven maven 官网下载压缩包 &#xff0c;并将其传输到服务器&#xf…

【热门话题】计算机视觉入门:探索数字世界中的“视觉智能”

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 计算机视觉入门&#xff1a;探索数字世界中的“视觉智能”摘要正文一、计算机视…

scoped原理及使用

一、什么是scoped&#xff0c;为什么要用 在vue文件中的style标签上&#xff0c;有一个特殊的属性&#xff1a;scoped。 当一个style标签拥有scoped属性时&#xff0c;它的CSS样式就只能作用于当前的组件&#xff0c;通过该属性&#xff0c;可以使得组件之间的样式不互相污染。…

重构智能防丢产品,苹果Find My技术引领市场发展

目前市场上最主要的防丢技术是蓝牙防丢和GPS防丢&#xff0c;蓝牙防丢是通过感应防丢器与绑定手机的距离来实现防丢的。一般防丢会默认设置一个最远安全距离&#xff0c;超过这个安全距离后&#xff0c;与手机蓝牙信号断开&#xff0c;触发防丢报警&#xff0c;用户根据防丢报警…

Shell GPT:直接安装使用的chatgpt应用软件

ShellGPT是一款基于预训练生成式Transformer模型&#xff08;如GPT系列&#xff09;构建的智能Shell工具。它将先进的自然语言处理能力集成到Shell环境中&#xff0c;使用户能够使用接近日常对话的语言来操作和控制操作系统。 官网&#xff1a;GitHub - akl7777777/ShellGPT: *…

深度学习理论基础(三)封装数据集及手写数字识别

目录 前期准备一、制作数据集1. excel表格数据2. 代码 二、手写数字识别1. 下载数据集2. 搭建模型3. 训练网络4. 测试网络5. 保存训练模型6. 导入已经训练好的模型文件7. 完整代码 前期准备 必须使用 3 个 PyTorch 内置的实用工具&#xff08;utils&#xff09;&#xff1a; ⚫…

TXT文本高效编辑神器,教你进行隔行删除不需要的内容,轻松整理文本内容。

在信息爆炸的时代&#xff0c;我们每天都会接触到大量的文本信息&#xff0c;无论是工作中的报告、邮件&#xff0c;还是生活中的读书笔记、备忘录&#xff0c;都需要我们对文本进行高效的管理和编辑。然而&#xff0c;传统的文本编辑方式往往繁琐低效&#xff0c;无法满足我们…

PTA L2-048 寻宝图

给定一幅地图&#xff0c;其中有水域&#xff0c;有陆地。被水域完全环绕的陆地是岛屿。有些岛屿上埋藏有宝藏&#xff0c;这些有宝藏的点也被标记出来了。本题就请你统计一下&#xff0c;给定的地图上一共有多少岛屿&#xff0c;其中有多少是有宝藏的岛屿。 输入格式&#xf…

LeetCode练习题--567.字符串的排列

今天讲一个非常经典的滑动窗口的问题 这道题的意思很明显: 给你两个字符串s1与s2,判断s2中是否存在一个子串:它包含s1中所有字符且不包含其他字符 让我们先来写一下滑动窗口的模板: /*** 滑动窗口模板 * param s1 * param s2 */public static void model (String s1, String s2…

51单片机入门:认识开发板

认识开发板 板载资源&#xff1a; 数码管模块 说明&#xff1a; 2个四位一体共阴数码管 详细&#xff1a; 2个四位一体&#xff1a;两个独立的四位数码管&#xff0c;每个四位数码管都是“一体”的设计&#xff0c;也就是说&#xff0c;每个数码管内部集成了四个独立的七段LE…

HTTPS跟HTTP有区别吗?

HTTPS和HTTP的区别&#xff0c;白话一点说就是&#xff1a; 1. 安全程度&#xff1a; - HTTP&#xff1a;就像是你和朋友面对面聊天&#xff0c;说的话大家都能听见&#xff08;信息明文传输&#xff0c;容易被偷听&#xff09;。 - HTTPS&#xff1a;就像是你们俩戴着加密耳机…

论大数据服务化发展史

引言 一直想写一篇服务化相关的文章&#xff0c;那就别犹豫了现在就开始吧 正文 作为大数据基础架构工程师&#xff0c;业界也笑称“运维Boy”&#xff0c;日常工作就是在各个机器上部署以及维护服务&#xff0c;例如部署Hadoop、Kafka、Pulsar这些等等&#xff0c;用于给公…

InternLM2-lesson2笔记

书生浦语大模型趣味 Demo 视频连接&#xff1a;https://www.bilibili.com/video/BV1AH4y1H78d/?vd_source902e3124d4683c41b103f1d1322401fa 目录 书生浦语大模型趣味 Demo课程总览SIG项目Demo部署的一般流程存在的问题总结 课程总览 InternLM2-chat-1.8B部署八戒-chat-1.8B…

【css】文本过长溢出一行不换行普通css以及antd实现

.text-box { white-space: nowrap; /* 防止文字换行 */ overflow: hidden; /* 隐藏超出div的内容 */ text-overflow: ellipsis; /* 当内容超出时&#xff0c;显示省略号 */ max-width: calc(100% - 80px); /* 假设按钮宽度为80px&#xff0c;则设置div的最大宽度为容器宽度…

Mysql索引总结(1)

文章目录 InnoDB索引与MyISAM索引实现的区别是什么&#xff1f;一个表中如果没有创建索引&#xff0c;那么还会创建B树吗&#xff1f;B树索引实现原理&#xff08;数据结构&#xff09; InnoDB索引与MyISAM索引实现的区别是什么&#xff1f; MyISAM的索引方式都是非聚簇的&…

07-app端文章搜索

app端文章搜索 1) 今日内容介绍 1.1)App端搜索-效果图 1.2)今日内容 文章搜索 ElasticSearch环境搭建 索引库创建 文章搜索多条件复合查询 索引数据同步 搜索历史记录 Mongodb环境搭建 异步保存搜索历史 查看搜索历史列表 删除搜索历史 联想词查询 联想词的来源 联…

elasticSearch原理浅尝

终于等到你 马上就要放弃 开个玩笑 &#xff0c;进入正题 on fire 基础的咱不说了&#xff0c;一搜一麻袋 读 全文检索&#xff1a; 协调节点广播查询请求到相关分片 并 将其响应 整合 全局排序 返回结果集合 带路由&#xff1a;具体文档 shard hash(document_id) % (…

redis进阶入门主从复制与哨兵集群

一、主从复制 1.1背景 一般来说&#xff0c;要将 Redis用于工程项目中&#xff0c;只使用一台 Redist是万万不能的&#xff0c;原因如下&#xff1a; 从结构上&#xff0c;单个 Redist服务器会发生单点故障&#xff0c;井且一台服务器需要处理所有的请求负載&#xff0c;压力…

HTML基础知识详解(上)(如何想知道html的全部基础知识点,那么只看这一篇就足够了!)

前言&#xff1a;在学习前端基础时&#xff0c;必不可少的就是三大件&#xff08;html、css、javascript &#xff09;&#xff0c;而HTML&#xff08;超文本标记语言——HyperText Markup Language&#xff09;是构成 Web 世界的一砖一瓦&#xff0c;它定义了网页内容的含义和…

物联网实战--驱动篇之(一)EEPROM存储器(AT24C64)

目录 一、驱动概述 二、AT24C64简介 三、驱动编写 四、驱动应用 一、驱动概述 这是驱动篇的第一篇&#xff0c;所以先说明下驱动篇的作用和书写计划。之前的净化器项目已有提及&#xff0c;向ESP8266、SHT30这些都属于驱动设备&#xff0c;主芯片STM32是核心&#xff0c;相…