算法模板 5.十大排序

十大排序

在这里插入图片描述

复杂度 / 稳定性

在这里插入图片描述

交换两元素的3种方法

利用临时数tmp

void swap(int q[], int i, int j){int tmp = q[i];q[i] = q[j];q[j] = tmp;
}

加减法

使用加减法,有可能导致溢出。

void swap_cal(int q[], int i, int j){if(i == j) return;q[i] = q[i] + q[j];q[j] = q[i] - q[j];q[i] = q[i] - q[j];
}

异或

void swap_xor(int q[], int i, int j){if(i == j) return;q[i] ^= q[j];//a = a ^ bq[j] ^= q[i];//b = (a ^ b) ^ b = a ^ (b ^ b) = a ^ 0 = aq[i] ^= q[j];//a = (a ^ b) ^ a = (a ^ a) ^ b = 0 ^ b = b
}

快速排序

具体思路如下:

  1. 在区间中取一个值x
  2. 通过双指针 i , j 的方式,将一个区间分成两段,左边的值小于x,右边的值大于x
  3. 递归,分别排序左边区间[l , j] 和右边区间[j+1,r]
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
int q[N];
void quick_sort(int q[],int l,int r){if(l >= r)  return;//如果只有1个元素或者l<r 则返回int x = q[l+r>>1],i = l - 1,j = r + 1;//定义x,取中点的值,定义双指针,这里要定义在往区间外部扩1(由于下面双指针编程决定的)while(i < j){while(q[++i] < x);//移动直到左段中q[i]大于xwhile(q[--j] > x);//移动直到右段中q[i]小于xif(i < j) swap(q[i],q[j]);//交换这两个元素//本来交换完是要再次移动的,但在q[++i]和q[--j]中实现了先移动再判断大小}//递归快排quick_sort(q , l , j);//[l,j]quick_sort(q , j + 1 , r);//[j+1,r]
}
int main(){int n;scanf("%d",&n);for(int i=0;i<n;i++)    scanf("%d",&q[i]);//读数据quick_sort(q,0,n-1);for(int i=0;i<n;i++)    printf("%d ",q[i]);//打印return 0;
}

归并排序

具体思路如下:

  1. 取区间的中点
  2. 递归排序左边区间和右边区间
  3. 通过双指针 i , j 的方式,将两段有序区间合并成一段区间
  4. 将合并完的区间赋值到原区间
#include <bits/stdc++.h>
using namespace std;const int N=100010;int q[N],temp[N];void merge_sort(int q[],int l,int r){if(l >= r)    return;int mid = l + r>>1,i = l,j = mid + 1;int k = 0;merge_sort(q,l,mid);merge_sort(q,mid + 1,r);while(i <= mid && j <= r){if(q[i] <= q[j]){temp[k++] = q[i++];}else temp[k++] = q[j++];}while(i <= mid) temp[k++]=q[i++];while(j <= r) temp[k++]=q[j++];for(int t=0;t<k;t++){q[l+t]=temp[t];}
}
int main(){int n;scanf("%d",&n);for(int i=0;i<n;i++)    scanf("%d",&q[i]);//memset(temp,0,sizeof(temp));merge_sort(q,0,n-1);for(int i=0;i<n;i++)    printf("%d ",q[i]);return 0;
}

冒泡排序

思想:每次寻找一组数据中最大的元素,两两比较,找到后放到数据的最后一位。n个数据第一次两两比较n-1次。
第二次比较n-2次,比较的时候如果前一个元素比第二个元素大则相互交换。
总共两层循环:第一层代表需对比几轮;第二层代表需要两两对比多少次.

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int MOD = 1e9 + 7, N = 1e5 + 10;
int q[N];
int n;
void bubble_sort(){for(int i = 0; i < n - 1; i++){//第i轮for(int j = 0; j < n - 1 - i; j++){//把第i轮最大的元素移动到第n-i-1的位置if(q[j] > q[j+1]) swap(q[j],q[j+1]); }}
}int main()
{scanf("%d", &n);for(int i = 0; i < n; i++) scanf("%d", &q[i]);bubble_sort();for(int i = 0; i < n; i++) printf("%d ", q[i]);return 0;
}

选择排序

和冒泡排序类似,但是选择排序每轮只交换一次。

每轮记录最小的数字下标,然后和最前面的数字进行交换(swap(q[i] , q[minIdx]) ),重复上述过程,重复n-1轮。是不稳定排序,如772,第一轮会把第一个7和2进行交换。

void selection_sort(){for (int i = 0; i < n - 1; i++){int minIdx = i;for (int j = i + 1; j < n; j++){if(q[j] < q[minIdx]) minIdx = j;}if(minIdx != i) swap(q[i],q[minIdx]);}
}

插入排序

对于待排序数组,从第 2 个元素开始 (称作插入对象元素) ,比较它与之前的元素 (称作比较对象元素) ,当插入对象元素小于比较对象元素时,继续往前比较,直到不小于 (≥) 比较对象,此时将插入对象元素插入到该次比较对象元素之后。

重复这个插入过程直到最后一个元素作为插入对象元素完成插入操作。

以下是简单插入排序:

void insertion_sort(){if (n < 2) return;   for (int i = 1; i < n; i++){int target = q[i], j = i - 1;//向左搜索插入位置while (j >= 0 && target < q[j]){q[j + 1] = q[j];j--;}q[j + 1] = target; // 插入目标值}
}

折半插入排序:(其实就是把向左搜索插入位置改成二分查找),虽然查找的时间复杂度为Ologn但是线性移动复杂度为On,因此总的时间复杂度还是On方

希尔排序

希尔排序(Shell Sort)是插入排序的一种,它是针对直接插入排序算法的改进。

希尔排序实质上是一种分组插入方法。它的基本思想是:对于n个待排序的数列,取一个小于n的整数gap(gap被称为步长)将待排序元素分成若干个组子序列,所有距离为gap的倍数的记录放在同一个组中;然后,对各组内的元素进行直接插入排序。 这一趟排序完成之后,每一个组的元素都是有序的。然后减小gap的值,并重复执行上述的分组和排序。重复这样的操作,当gap=1时,整个数列就是有序的。

void shell_sort1(int a[], int n)
{int i,j,gap;// gap为步长,每次减为原来的一半。for (gap = n / 2; gap > 0; gap /= 2){// 共gap个组,对每一组都执行直接插入排序for (i = 0 ;i < gap; i++){for (j = i + gap; j < n; j += gap) {// 如果a[j] < a[j-gap],则寻找a[j]位置,并将后面数据的位置都后移。(下面这个部分就是插入排序)if (a[j] < a[j - gap]){int tmp = a[j];int k = j - gap;while (k >= 0 && a[k] > tmp){a[k + gap] = a[k];k -= gap;}a[k + gap] = tmp;}}}}
}

堆排序

手写大根堆,主要是建堆和下滤down操作。

以下代码是输入n个数,堆排后(从小到大)输出前m个数

#include <bits/stdc++.h>using namespace std;const int N = 100010;int h[N],cnt;void down(int u){int t = u;if(u * 2 <= cnt && h[u * 2] < h[t]) t = u * 2;if(u * 2 + 1 <= cnt && h[u * 2 + 1] < h[t]) t = u * 2 + 1;if(t!=u){swap(h[t],h[u]);down(t);}
}int main(){int n,m;scanf("%d%d",&n,&m);for(int i = 1;i <= n;i++)  scanf("%d",&h[i]);cnt = n;for(int i = n/2;i;i--)  down(i);while(m--){cout << h[1] << " ";h[1] = h[cnt];//把第一个元素 替换为最后一个元素 即最大的元素,然后再down一遍cnt--;down(1);}return 0;
}

计数排序

在这里插入图片描述

void counting_sort(){if(n < 2) return;int minVal = q[0], maxVal = q[0];for (int i = 1; i < n; i++){minVal = min(minVal, q[i]);maxVal = max(maxVal, q[i]);}vector<int> arr(maxVal - minVal + 1);for (int i = 0; i < n; i++){arr[q[i] - minVal]++;//计数}int idx = 0;for(int i = 0; i < (maxVal - minVal + 1); i++){for(int j = 0; j < arr[i]; j++){q[idx] = i + minVal;idx++;}}
}

桶排序

在这里插入图片描述

先对元素进行划分桶,然后对每个桶进行内部排序,最后根据桶序和桶内部序依次输出。

void bucketSort(int a[], int n, int N)
{int i,j;int buckets[N];//根据值域创建N个桶,假设每个单元都是一个桶// 将buckets中的所有数据都初始化为0。memset(buckets, 0, N * sizeof(int));// 1. 计数for(i = 0; i < n; i++) buckets[a[i]]++; // 2. 排序(计数排序)for (i = 0, j = 0; i < N; i++) {while( (buckets[i]--) >0 )a[j++] = i;//输出}
}

基数排序

基数排序(Radix Sort)是桶排序的扩展,它的基本思想是:将整数按位数切割成不同的数字,然后按每个位数分别比较。
具体做法是:将所有待比较数值统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后, 数列就变成一个有序序列。

/*获取数组元素最大值*/
int get_max(int a[], int n)
{int i, max;max = a[0];for (i = 1; i < n; i++)if (a[i] > max)max = a[i];return max;
}/** 对数组按照"某个位数"进行排序(桶排序)** 参数说明:*     a -- 数组*     n -- 数组长度*     exp -- 指数。对数组a按照该指数进行排序。** 例如,对于数组a={50, 3, 542, 745, 2014, 154, 63, 616};*    (01) 当exp=1表示按照"个位"对数组a进行排序*    (02) 当exp=10表示按照"十位"对数组a进行排序*    (03) 当exp=100表示按照"百位"对数组a进行排序*    ...*/
void count_sort(int a[], int n, int exp)
{int output[n];             // 存储"被排序数据"的临时数组int i, buckets[10] = {0};// 将数据出现的次数存储在buckets[]中for (i = 0; i < n; i++)buckets[ (a[i] / exp) % 10 ]++;// 更改buckets[i]。目的是让更改后的buckets[i]的值,是该数据在output[]中的位置。for (i = 1; i < 10; i++)buckets[i] += buckets[i - 1];// 将数据存储到临时数组output[]中for (i = n - 1; i >= 0; i--){output[buckets[ (a[i]/exp) % 10 ] - 1] = a[i];buckets[ (a[i] / exp) % 10 ]--;}// 将排序好的数据赋值给a[]for (i = 0; i < n; i++)a[i] = output[i];
}/** 基数排序** 参数说明:*     a -- 数组*     n -- 数组长度*/
void radix_sort(int a[], int n)
{int exp;    // 指数。当对数组按各位进行排序时,exp=1;按十位进行排序时,exp=10;...int max = get_max(a, n);    // 数组a中的最大值// 从个位开始,对数组a按"指数"进行排序for (exp = 1; max/exp > 0; exp *= 10)count_sort(a, n, exp);
}

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

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

相关文章

基于布谷鸟搜索的多目标优化matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 1. 布谷鸟搜索算法基础 2. 多目标优化问题 3. 基于布谷鸟搜索的多目标优化算法 4. 解的存储和选择策略 5.算法步骤 5.完整程序 1.程序功能描述 基于布谷鸟搜索的多目标优化&#xff0c;…

android 网络拦截器统一处理请求参数和返回值加解密实现

前言 项目中遇到参数加密和返回结果加密的业务 这里写一下实现 一来加深记忆 二来为以后参考铺垫 需求 项目在开发中涉及到 登陆 发验证码 认证 等前期准备接口 这些接口需要单独处理 比如不加密 或者有其他的业务需求 剩下的是登陆成功以后的业务需求接口 针对入参和返回值…

npm ERR! reason: certificate has expired(淘宝镜像过期)

npm ERR! request to https://registry.npm.taobao.org/yauzl/-/yauzl-2.4.1.tgz failed, reason: certificate has expired 今天在执行npm install命令时&#xff0c;报错百度了下是淘宝证书过期原因 解决方法一 执行下面两个命令再进行npm install即可 npm cache clean --…

在Python中处理HTTP代理的验证:一场与“门卫“的友好交流

各位魔法探险家们&#xff0c;今天我们要一起学习如何在Python中处理HTTP代理的验证&#xff0c;这可是一场与"门卫"的友好交流啊&#xff01; 首先&#xff0c;我们要明白什么是HTTP代理的验证。简单来说&#xff0c;就像魔法世界的"门卫"一样&#xff0…

springBoot - mybatis 多数据源实现方案

应用场景: 多数据源 小型项目 或者 大项目的临时方案中比较常用.在日常开发中,可能我们需要查询多个数据库,但是数据库实例不同,导致不能通过 指定schema的方式 区分不同的库, 这种情况下就需要我们应用程序配置多数据源 实现方式: 首先自定义实现 datasource数据源 为当前…

【Django-ninja】分页管理器

django ninja通过paginate装饰器即可进行分页。内置了两个分页管理器LimitOffsetPagination和PageNumberPagination&#xff0c;能够实现基本的分页要求。当内置分页器不满足要求时&#xff0c;可以继承PaginationBase进行扩展自己的分页管理器。 1 使用分页器 from ninja.pa…

记录一次使用ant design 中 ConfigProvider来修改样式导致样式改变的问题(Tabs嵌套Tabs)

一 说明 继之前的一篇文章&#xff1a;antd5 Tabs 标签头的文本颜色和背景颜色修改 后&#xff0c;发现在被修改后的Tab中继续嵌套Tabs组件&#xff0c;这个新的Tabs组件样式跟外层Tabs样式也是一致的&#xff0c;如下图所示&#xff1a; 二 原因 在修改外层tabs样式时&…

AIGC领域又有大动作了!AI视频“黑马”Morph Studio 来袭,1080P高清画质视频免费生成!

起初小编也不知道 Morph Studio&#xff0c;也是从AIGC美少女、AI电影导演 海辛Hyacinth 口中知晓&#xff0c;因为她在2024年刚加入了 Morph Studio公司。 废话不多数&#xff0c;接下来小编则为大家介绍下 Morph Studio 这个初创公司开发了一个什么样的产品&#xff0c;而引起…

CHS_08.2.3.6_1+生产者-消费者问题

CHS_08.2.3.6_1生产者-消费者问题 问题描述问题分析思考&#xff1a;能否改变相邻P、V操作的顺序&#xff1f;知识回顾 在这个小节中 我们会学习一个经典的进程同步互斥的问题 问题描述 并且尝试用上个小节学习的p v操作 也就是信号量机制来解决这个生产者消费者问题 问题的描…

Codeforces Round 651 (Div. 2)C 博弈 奇偶数 偶数的表示

Submission #244500083 - Codeforces 题目&#xff1a; 思路&#xff1a; 此题要从奇偶性上入手。&#xff08;注意除的是奇因数&#xff0c;即一个奇数。我想成质数了&#xff09; 1.当A选手开局是1时&#xff0c;A败。 2.当A选手开局是2和奇数时&#xff0c;A必胜。&…

2024 美国大学生数学建模竞赛(F题)减少非法野生动物贸易 | 建模秘籍文章代码思路大全

铛铛&#xff01;小秘籍来咯&#xff01; 小秘籍团队独辟蹊径&#xff0c;以蒙特卡洛模拟、决策树、博弈论等强大工具&#xff0c;构建了解决复杂问题的独特方案。深度学习和Kano模型的妙用&#xff0c;为降低非法野生动物贸易提供新视角。通过综合分析&#xff0c;描绘出概率、…

Stable diffusion使用和操作流程

Stable Diffusion是一个文本到图像的潜在扩散模型,由CompVis、Stability AI和LAION的研究人员和工程师创建。它使用来自LAION-5B数据库子集的512x512图像进行训练。使用这个模型,可以生成包括人脸在内的任何图像,因为有开源的预训练模型,所以我们也可以在自己的机器上运行它…