C++排序

  • 冒泡排序
  • 选择排序
  • 插入排序
  • 希尔排序
  • 快速排序
  • 归并排序
  • 堆排序
  • 排序总结

排序目的:把无序的数据元素排成有序的数据元素
排序的稳定性:
如果在序列中有两个数据元素r[i]和r[j],它们的关键字k[i] ==k[j],且在排序之前,对象r[i]排在r[j]前面。如果在排序之后,对象r[i]仍在r[j]前面,则称这个排序方法是稳定的,否则称这个排序方法是不稳定的。
即两个相等的数据元素原来在前面的,排序后还是在前面


比较和交换是排序的基本操作
多关键字排序与单关键字排序无本质区别
排序的时间性能 是区分排序算法好坏的主要因素
时间性能:关键性能差异体现在比较和交换的数量
辅助存储空间:为完成排序操作需要的额外的存储空间,必要时可以“空间换时间”
算法的实现复杂性:过于复杂的排序法会影响代码的可读性和可维护性,也可能影响排序的性能

冒泡排序

冒泡排序是一种 稳定 的排序算法,冒泡排序的效率:O(n²)

思路: 从第一个元素开始,依次比较相邻的元素,满足条件就交换,一轮下来可以确定一个最大/最小的。每一轮减少一个元素,重复上述步骤,进行n-1轮比较。

优点:比较简单,空间复杂度较低,是稳定的
缺点:时间复杂度太高,效率不好

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include <time.h>
#define MAX 10
//交换
void Swap(int* a, int* b) {int temp = *a;*a = *b;*b = temp;
}
//冒泡排序
void BubbleSort(int arr[],int length) {for (int i = 0; i < length - 1 ; i++) {for (int j = 0; j < length - i - 1; j++) {if (arr[j] > arr[j + 1]) {      //从小到大 升序Swap(&arr[j], &arr[j + 1]);}}}
}
//冒泡法二
void BubbleSort2(int arr[], int length) {for (int i = 0; i < length - 1 ; i++) {for (int j = length - 1; j > i; j--) {if (arr[j - 1] > arr[j]) {       //从小到大 升序Swap(&arr[j - 1], &arr[j]);}}}
}
//冒泡法三
void BubbleSort3(int arr[],int length) {for (int i = 1; i <= length - 1; i++) {   //N-1轮for (int j = 0; j < length - i; j++) {if (arr[j] > arr[j + 1]) {   //从小到大 升序Swap(&arr[j], &arr[j + 1]);}}}
}//打印
void PrintArray(int arr[], int length) {for (int i = 0; i < length; i++) {printf("%d ", arr[i]);}printf("\n");
}int main() {int arr[MAX];srand((unsigned int)time(NULL));for (int i = 0; i < MAX; i++) {arr[i] = rand() % 100;}PrintArray(arr, MAX);BubbleSort(arr, MAX);PrintArray(arr, MAX);return 0;
}

冒泡法升级版
改进版增加了flag标识符,记录序列是否已经有序,减少循环交换次数

//冒泡排序升级版
void BubbleSort(int arr[],int length){int flag = 0;    //标识符 0代表没有排序好 1代表排好for (int i = 0; i < length - 1 && flag == 0; i++){flag = 1;    //认为已经排序好for (int j =  length - 1; j > i;j--){//if (arr[j-1] < arr[j]){      //降序 从大到小if (arr[j-1] > arr[j]){         //升序 从小到大num++;flag = 0;Swap(&arr[j - 1],&arr[j]);}}}
}

冒泡排序是一种效率低下的排序方法,在数据规模很小时,可以采用。数据规模比较大时,最好用其它排序方法

选择排序

选择排序是 不稳定 的排序方法,选择排序效率:O(n²)

思路:每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。

优点:移动数据的次数已知(n-1 次);
缺点:比较次数多。

//选择排序
void SelectSort(int arr[],int length){for (int i = 0; i < length-1;i ++){     //N-1轮int min = i;     //保存每轮最小值的下标for (int j = i + 1; j < length; j++){if (arr[j] < arr[min]){min = j;}}if (min != i){Swap(&arr[min],&arr[i]);}}
}

插入排序

插入排序是 稳定 的排序算法, 插入排序效率:O(n²)
适合情况
1.元素基本有序
2.元素个数比较少

思路:把无序分开 变有序,刚开始第一个单个元素,就认为是有序的,然后后面的元素逐个插入到有序中,用temp保存此值,与前面有序的比较,找到合适位置插入,直到插完后面所有元素为止

优点:稳定,快;
缺点:比较次数不一定,插入后的数据移动多,特别是当数据总量庞大的时候,但用链表可以解决这个问题。

//插入排序
void InsertSort(int arr[],int length){int j;for (int i = 1; i < length;i ++){if (arr[i] < arr[i-1]){       //从小到大 升序int temp = arr[i];        //临时保存后面对比元素for (j = i - 1; j >= 0 && temp < arr[j];j--){arr[j + 1] = arr[j];}arr[j + 1] = temp;        //注意是要+1,因为经过循环--后}}
}

希尔排序

希尔排序的实质就是 分组插入排序,又叫减少增量排序
希尔排序是 不稳定 的排序算法,希尔排序效率:O(nlog2n)

思路:先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。因为直接插入排序在元素基本有序的情况下(接近最好情况),效率是很高的
即先分组,然后对每组分别进行插入排序,然后减小增量再分组,然后再插入排序,最后增量为一,就排序完成。

增量一般为:步长=步长/3 + 1
优点:快,数据移动少
缺点:不稳定,增量的取值无确切答案,只能凭经验来取。

//希尔排序
void ShellSort(int arr[], int length){int increasement = length;int i, j,k;do{//确定分组的增量increasement = increasement / 3 + 1;//分组for (i = 0; i < increasement; i++){//遍历每一分组并对每一组的元素进行插入排序for (j = i + increasement; j < length; j += increasement){      if (arr[j] < arr[j-increasement] ){      //从小到大int temp = arr[j];for (k = j - increasement; k >= 0 && temp < arr[k];k -= increasement){arr[k + increasement] = arr[k];}arr[k + increasement] = temp;   //注意加上增量,因为前面for循环的-=}}}} while (increasement > 1);
}

快速排序

快速排序,挖坑填数
快速排序是 不稳定 的排序算法,快速排序效率:O(nlog2n)
思想:
先将第一个元素设为基准数,挖坑,然后从右到左,找小于基准数的数,填入坑中,此数变为坑,然后从左往右,找大于基准数的数,填入坑中,此数变为坑。一直循环,直到 i>=j 时退出,然后将基准数填到 i 或 j 中。以上只是一次填坑排序,然后要递归左右部分排序。所有的判断条件要满足 i<j

优点:极快,数据移动少;
缺点:不稳定。

void QuickSort(int arr[], int start, int end){int i = start;int j = end;//基准数int temp = arr[start]; if (i < j){while (i < j){//从右向左去找比基准数小的while (i<j && arr[j] >= temp ){j--;}//填坑if(i < j){arr[i] = arr[j];i++;}//从左向右 找比基准数大的数while (i < j && arr[i] < temp){i++;}//填坑if (i < j){arr[j] = arr[i];j--;}}//把基准数放到i位置arr[i] = temp;//对左半部分进行快速排序QuickSort(arr, start, i - 1);//对右半部分进行快速排序QuickSort(arr, i + 1, end);}
}

归并排序

归并排序是 稳定 的排序算法,归并算法效率:O(nlog2n)
思路:将数组分成二组,如果不是有序,再继续分,分成有序的,当分出来的小组只有一个数据时,可以认为这个小组有序了,然后再合并相邻的二个小组(两个组的数列分别比较,按大小顺序放到临时数组,当 j 序列放完而 i 序列还有数据,则把 i 序列剩下的直接放到临时数组后面。同理 j 序列)
即先递归分解数列,再合并数列,就完成了归并排序

优点:快,稳定
缺点 : 需要额外的存储空间

//合并算法 从小到大
void Merge(int arr[], int start, int end, int mid, int* temp){int i_start = start;int i_end = mid;int j_start = mid + 1;int j_end = end;//表示辅助空间有多少个元素int length = 0;//合并两个有序序列while (i_start <= i_end && j_start <= j_end){if(arr[i_start] < arr[j_start]){temp[length] = arr[i_start];length++;i_start++;}else{temp[length] = arr[j_start];j_start++;length++;}}//i序列while (i_start <= i_end){temp[length] = arr[i_start];i_start++;length++;}//j序列while (j_start <= j_end){temp[length] = arr[j_start];length++;j_start++;}//辅助空间数据覆盖原空间for (int i = 0; i < length;i++){arr[start + i] = temp[i];}}//归并排序
void MergeSort(int arr[],int start,int end,int* temp){if (start >= end){return;}int mid = (start + end) / 2;//分组//左半边MergeSort(arr,start,mid,temp);//右半边MergeSort(arr, mid + 1, end,temp);//合并Merge(arr,start,end,mid,temp);
}

堆排序

思路:将一个数组,相当于一个完全二叉树,先调整堆,初始化堆,即从下往上,从最后一个非叶子节点(下标为len/2-1)开始,与左右子节点交换排序,递归堆调整形成大顶堆,然后从上往下,堆顶元素与堆的最后一个元素交换形成前一部分的无序区和有序区最后一个元素,交换后不符合堆,再堆调整,然后再堆顶与无序区的"最后一个元素"交换(i=len-1),i- -,有序区逐渐增多,最后全部有序。

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;void PrintArray(int arr[],int len){for (int i = 0; i < len;i ++){cout << arr[i] << " ";}cout << endl;
}void MySwap(int arr[],int a,int b){int temp = arr[a];arr[a] = arr[b];arr[b] = temp;
}
/*@param myArr 待调整的数组@param index 待调整的结点的下标@param len 数组的长度
*/
void HeapAdjust(int arr[], int index, int len){//先保存当前结点的下标int max = index;//保存左右孩子的数组下标int lchild = index * 2 + 1;int rchild = index * 2 + 2;if (lchild < len && arr[lchild] > arr[max]){max = lchild;}if (rchild < len && arr[rchild] > arr[max]){max = rchild;}if (max != index){//交换两个结点MySwap(arr,max,index);HeapAdjust(arr,max,len);}
}//堆排序
void HeapSort(int myArr[], int len){//初始化堆for (int i = len / 2 - 1; i >= 0; i --){HeapAdjust(myArr,i,len);}//交换堆顶元素和最后一个元素for (int i = len - 1; i >= 0; i --){MySwap(myArr, 0, i);HeapAdjust(myArr, 0, i);}}int main(void){int myArr[] = {4,2,8,0,5,7,1,3,9};int len = sizeof(myArr) / sizeof(int);PrintArray(myArr, len);//堆排序HeapSort(myArr,len);PrintArray(myArr, len);return 0;
}

排序总结


C++几个常用的排序相关推荐

  1. 常用的排序算法的时间复杂度和空间复杂度

    常用的排序算法的时间复杂度和空间复杂度                                           1.时间复杂度 (1)时间频度 一个算法执行所耗费的时间,从理论上是不能算出 ...

  2. 5种JavaScript中常用的排序方法

    5种JavaScript中常用的排序方法 01.冒泡排序 通过相邻数据元素的交换,逐步将待排序序列变为有序序列,如果前面的数据大于后面的数据,就将两值进行交换,将数据进行从小到大的排序,这样对数组的第 ...

  3. STL常用的排序算法

    常用的排序算法 merge() sort() random_shuffle() reverse() merge() 以下是排序和通用算法:提供元素排序策略 merge: 合并两个有序序列,存放到另一个 ...

  4. 常用的排序算法的时间复杂度和空间复杂度 .

    常用的排序算法的时间复杂度和空间复杂度 排序法 最差时间分析 平均时间复杂度 稳定度 空间复杂度 冒泡排序 O(n2) O(n2) 稳定 O(1) 快速排序 O(n2) O(n*log2n) 不稳定 ...

  5. php递归算法排序,php常用的排序算法代码[冒泡,递归排序-PHP源码

    <script>ec(2);<script> php 常用的排序算法代码[冒泡,递归排序 冒泡排序算法 function bubblesort($arr) { $n=count ...

  6. JAVA最常用的排序_冒泡排序、选择排序、快速排序

    排序算法是Java面试题中最常考的,笔试题.机试题都会有,所有掌握最常用的排序是必须. 在效率中快速排序是这几种效率最高的. 代码验证过,可以直接复制测试运行. 代码如下: package com.l ...

  7. 插入排序 php,常用的排序算法(二)--插入排序(PHP实现)

    常用的排序算法系列 插入排序 插入排序是一种逻辑上非常好理解的排序方式,整个排序的核心就是不断在当前已经排好部分数据的数组里,找到合适的位置插入新数据.就像抓扑克牌,抓一张,然后再手里已经部分已经排好 ...

  8. Numpy——常用的排序函数

    1 前言 今天在学习NMS算法~ 在学习别人的代码时,看到一句代码挺奇怪的, 这一句代码不是很懂,后来请教了一下度娘然后明白啦~ ("[::1]"是将数组进行翻转的操作~) 2 常 ...

  9. php1到5000排序,常用的排序算法(一)--快速排序(PHP实现)

    常用的排序算法系列 快速排序 假设当前需要从小到大进行排序,快速排序的核心思路是,从当前数组中,找到一个元素作为基准比较值(key),分别从两个方向进行比较.从后往前找,比key小元素放在数组前面.然 ...

  10. C基础 工程中常用的排序

    引言 - 从最简单的插入排序开始 很久很久以前, 也许都曾学过那些常用的排序算法. 那时候觉得计算机算法还是有点像数学. 可是脑海里常思考同类问题, 那有什么用呢(屌丝实践派对装逼学院派的深情鄙视). ...

最新文章

  1. java递归获取文件名_递归打印文件名
  2. 《走进SAP(第2版)》——第2章 企业软件的SAP之路2.1 企业资源计划(ERP)...
  3. Apache、php、mysql默认安装路径
  4. 最短路算法整理 1557 热浪
  5. 只用jsp实现同样的Servlet功能
  6. 十二、Powerbi绘制人员地区分布图和后期学习
  7. 【线性筛】【质因数分解】【约数个数定理】hdu6069 Counting Divisors
  8. PyTorch官方教程中文版:入门强化教程代码学习
  9. 本表收录的字符的Unicode编码范围为19968至40869
  10. CentOS 7防火墙开启路由功能和开放特定端口
  11. Java基础-异常-throws Exception-抛声明
  12. 关于在平台中设置系统全局变量的使用和场景
  13. override java field_JAVA方法的重载(overload)和覆盖(override)
  14. 记所内部“与顶级会议作者面对面”系列学术活动交流感受
  15. 红黑树、B树、B+树各自适用的场景
  16. python爬虫爬取微信公众号的阅读数、喜爱数、文章标题和链接等信息
  17. wifi微信连不到服务器,微信连不上wifi怎么办?
  18. 苹果工具条_如何在苹果官网获取 iOS 13 描述文件?iOS 13 公测版升级教程
  19. 钉钉小程序内嵌web网页
  20. 【前端】JS 计算贷款月付

热门文章

  1. 力扣887题-鸡蛋掉落
  2. 2022-2027年中国番茄酱行业市场全景评估及发展战略规划报告
  3. 神经机器翻译中的曝光偏差,幻觉翻译与跨域稳定性
  4. 湖南科技大学EDA作业
  5. 计算机应用专业毕业感言,大学毕业感言一句话
  6. 移动端轮播图——网易云音乐手机端样式
  7. SQL-Server笔记
  8. 【2018亚太数据中心峰会】林峰:中国游戏打破传统模式立足国际舞台
  9. 2019第五届美亚杯全国电子数据取证大赛团队赛wp
  10. python列表append方法_Python列表append()方法