冒泡排序

冒泡排序介绍:
冒泡排序(Bubble Sort),是一种计算机科学领域的较简单的排序算法。
它重复地跑过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小)那么它就会按照大到小的排序方式来。它必须要把算所有的元素重复地进行跑一遍,直到没有相邻元素需要交换,也就是说该元素列已经排序完成。

冒泡排序算法的原理如下:
1,比较相邻的元素。如果第一个比第二个大,就交换他们两个,如果不是相等的就跳过比下面的元素 ,这样依次的循环下去 直到所有的元素都比较完成才结束。
2,针对所有的元素重复以上的步骤,除了最后一个。
3,持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

冒泡排序代码如下:

//冒泡排序
#include<stdio.h>
int main(void)
{int Array[10] = { 5,3,7,2,8,2,8,22,7 ,6 };int Num = 10, temp;bool Sorted = true;while (Sorted){Sorted = false;       //假设没有交换for (int i = 0; i < Num - 1; i++){if (Array[i + 1] > Array[i]){Sorted = true;              //如果有交换重新把Sorted设置为 truetemp = Array[i + 1];Array[i + 1] = Array[i];Array[i] = temp;}}Num--;}for (int i = 0; i < 10; i++){printf("%d  ", Array[i]);}
}

选择排序

选择排序介绍:
选择排序是通过每一趟排序过程中从待排序记录中选择出关键字最小(大)的记录,将其依次放在数据表的最前或最后端的方法来实现整个数据表的有序排列。

选择排序算法的原理如下:
第一趟排序在所有待排序的n个记录中选出关键字最小的记录,将它与数据表中的第一个记录交换位置,使关键字最小的记录处于数据表的最前端;第二趟在剩下的n-1个记录中再选出关键字最小的记录,将其与数据表中的第二个记录交换位置,使关键字次小的记录处于数据表的第二个位置;重复这样的操作,依次选出数据表中关键字第三小、第四小…的元素,将它们分别换到数据表的第三、第四…个位置上。排序共进行n-1趟,最终可实现数据表的排列。

选择排序代码如下:

//选择排序
#include<stdio.h>
int main(void)
{int Array[10] = { 5,4,7,3,8,3,8,21,87,24 };int temp, min;for (int i = 0; i < 10; i++){min = i;for (int j = i + 1; j < 10; j++){if (Array[min] < Array[j])         min = j;}if (min != i)                     {temp = Array[min];Array[min] = Array[i];Array[i] = temp;}}for (int i = 0; i < 10; i++){printf("%d   ", Array[i]);}
}

冒泡排序和选择排序的区别

区别在于:在交换的方式上

冒泡算法,每次比较如果发现较小的元素在,就交换两个相邻的元素。

而选择排序算法的改进在于:先并不急于调换位置,先从A[1]开始逐个检查,看哪个数最小就记下该数所在的位置P,等一躺扫描完毕,再把A[P]和A[1]对调,这时A[1]到A[10]中最小的数据就换到了最前面的位置。

所以,选择排序每扫描一遍数组,只需要一次真正的交换,而冒泡可能需要很多次。比较的次数一样的。

例如:1 2 3 4我们分别用a[0],a[1],a[2],a[3]存储。假设从大到小排序

选择排序,是a[0]和a[1],a[2],a[3]依次比较,遇到小的就交换,这样一次下来,最大的被保存在了a[0].下次排序就从a[1]开始重复以上步骤。

冒泡排序,是a[0]和a[1]比较,小的就交换。然后a[1]和a[2]比较,小的交换。然后a[2]和a[3]比较小的就交换。这样一次下来,最大的被保存在a[0]。下次排序从a[1]开始重复以上步骤。

虽然差不多,但是请注意:两者的比较方法是右差别的,一个事依次比下来,一个是俩俩比较。

冒泡排序的基本思想是将数组中的每个相邻元素进行两两比较,按照小元素在前(或大元素在前)的原则确定是否进行交换。这样每一轮执行之后,最大(或最小)的元素就会被交换到了最后一位,同样的过程会依次进行,直到所有元素都被排列成预期的顺序为止。这个过程是不是像是水中的起泡一个个冒起来的过程.

选择排序,顺序放在已排好序的数列的最后,直到全部待排序的数据元素排完。 选择排序是不稳定的排序方法。

插入排序

插入排序简介:
插入排序是将数组的第一个数认为是有序数组,从后往前(从前往后)扫描该有序数组,把数组中其余n-1个数,根据数值的大小,插入到有序数组中,直至数组中的所有数有序排列为止。这样的话,n个元素需要进行n-1趟排序!!!

举个例子:4个数字4,6,7,5进行从大到小的排序。前插排序法具体过程如下:
把第一个数4插入到空的有序数组中的第一个位置上,得到新数字序列4;

第一趟:从后往前扫描有序数组,将第二个数字6和有序数组中的4进行比较,6大于4,此时将4后移一个位置。此时已经扫描完有序数组中的数,将6插入到4的前面(有序数组的第一个位置),得到新数字序列6,4;

第二趟:从后往前扫描有序数组,先将第三个数字7和有序数组中的4进行比较,7大于4,此时将4后移一个位置;再将7和有序数组中的6进行比较,7大于6,此时将6后移一个位置。此时已经扫描完有序数组中的数,将7插入到6的前面(有序数组的第一个位置),得到新数字序列7,6,4;

第三趟:从后往前扫描有序数组,先将第四个数字5和有序数组中的4进行比较,5大于4,此时将4后移一个位置;再将5和有序数组中的6进行比较,5小于6,由于有序数组就按照从大到小排列的,此时直接把5插入到4的前面即可!不需要再和7进行比较!最后,得到新数字序列7,6,5,4;

插入排序算法的原理如下:
直接插入排序的基本操作是将一个记录插入到已经排好的有序表中,从而得到一个新的、记录数增1的有序表。对于给定的一组记录,初始时假定第一个记录自成一个有序序列,其余记录为无序序列。接着从第二个记录开始,按照记录的大小依次将当前处理的记录插入到其之前的有序序列中,直到最后一个记录插到有序序列中为止。

插入排序代码如下:

//插入排序
#include<stdio.h>
int main()
{int array[10] = { 5,1,4,2,4,3,3,5,76,76 };for (int i = 1; i < 10; i++){int j = i - 1;int temp = array[i];while (j >= 0 && temp < array[j])        //如果temp小于array[j]一直交换{array[j + 1] = array[j];j--;            //递减}array[j + 1] = temp; //将array[i]与array[m+1]互换}//输出排序结果for (int i = 0; i < 10; i++){printf("%d ", array[i]);}return 0;
}

并归排序

并归排序简介
归并排序(Merge Sort)就是利用归并的思想实现的排序方法。它的原理是假设初始序列有n个记录,则可以看成是n个有序的子序列,每个子序列的长度为1,然后两两归并,得到⌈n/2⌉个长度为2或1的有序子序列;再两两归并,……,如此重复,直至得到一个长度为n的有序序列为止,这种排序方法称为2路归并排序。

并归排序算法的原理如下:`

设两个有序的子序列(相当于输入序列)放在同一序列中相邻的位置上:array[low…m],array[m + 1…high],先将它们合并到一个局部的暂存序列 temp (相当于输出序列)中,待合并完成后将 temp 复制回 array[low…high]中,从而完成排序。

在具体的合并过程中,设置 i,j 和 p 三个指针,其初值分别指向这三个记录区的起始位置。合并时依次比较 array[i] 和 array[j] 的关键字,取关键字较小(或较大)的记录复制到 temp[p] 中,然后将被复制记录的指针 i 或 j 加 1,以及指向复制位置的指针 p加 1。重复这一过程直至两个输入的子序列有一个已全部复制完毕(不妨称其为空),此时将另一非空的子序列中剩余记录依次复制到 array 中即可。

若将两个有序表合并成一个有序表,称为2 路归并。

并归排序代码如下:

//并归排序
#include<cstdio>
#include<iostream>
#include<cstdlib>
using namespace std;
int Array[10] = { 4,33,5,-3,4,6,44,6,-7,8 };void merge(int lo, int mi, int hi)    //[lo, mi)和[mi, hi)各自有序,lo < mi < hi
{int i = 0, j = 0, k = 0;         //计数器int* A = Array + lo;         //合并后的有序向量A[0, hi - lo) = Array[lo, hi),就地int lb = mi - lo;        //mi前面不包括miint lc = hi - mi;        //mi后面的包括miint* B = new int[lb];  //前子向量B[0, lb) <-- Array[lo, mi)for (int i = 0; i < lb; i++) B[i] = A[i];     //复制自A的前缀int* C = Array + mi;     //后子向量C[0, lc) = Array[mi, hi),就地while ((j < lb) && (k < lc))                      //反复地比较B、C的首元素A[i++] = (B[j] <= C[k]) ? B[j++] : C[k++]; //将更小者归入A中while (j < lb) //若C先耗尽,则A[i++] = B[j++]; //将B残余的后缀归入A中while (k < lc) //若C先耗尽,则A[i++] = C[k++]; //将C残余的后缀归入A中delete[] B; //释放临时空间:mergeSort()过程中,如何避免此类反复的new/delete?
}void mergeSort(int lo, int hi)
{if (hi - lo < 2)                 //递归终止条件return;int mi = (lo + hi) / 2;mergeSort(lo, mi);        //分别排序mergeSort(mi, hi);merge(lo, mi, hi);        //归并
}int main(void)
{mergeSort(0, 10);for (int i = 0; i < 10; i++){printf("%d ", Array[i]);}return 0;
}

快速排序

快速排序简介

快速排序,听这个名字就能想到它排序速度快,它是一种原地排序。其基本思想是随机找出一个数(通常就拿数组第一个数据就行),把它插入一个位置,使得它左边的数都比它小,它右边的数据都比它大,这样就将一个数组分成了两个子数组,然后再按照同样的方法把子数组再分成更小的子数组,直到不能分解为止。 它也是分治思想的一个经典实验(归并排序也是)

快速排序原理:

排序在各种场合经常被用到。
快速排序是十分常用的高效率的算法。

其思想是:先选一个“标尺”,用它把整个队列过一遍筛子,以保证:其左边的元素都不大于它,其右边的元素都不小于它。这样,排序问题就被分割为两个子区间。再分别对子区间排序就可以了。

快速排序代码如下:

//快速排序
#include<stdio.h>
int FindPos(int* AA, int lo, int hi)
{int val=AA[lo];           //等于需要排序区间的第一个元素while (lo < hi){while (lo < hi && AA[hi] >= val)        //如果AA[hi]大于val hi的值递减{--hi;}AA[lo] = AA[hi];        while (lo < hi && AA[lo] <= val)       //如果AA[lo]小于于val hi的值递增{++lo;}AA[hi] = AA[lo];}AA[lo] = val;return hi;
}void QuickSort(int* AA, int lo, int hi)
{int Pos;if (lo < hi)        //递归条件{Pos = FindPos(AA, lo, hi);QuickSort(AA, lo, Pos - 1);QuickSort(AA, Pos + 1, hi);}
}int main(void)
{int array[6] = { 3,-3,5,2,7,3 };QuickSort(array, 0, 5);for (int i = 0; i < 6; i++){printf("%d  ", array[i]);}
}

上述五种排序的测试结果

代码如下:

#include<cstdio>
#include<iostream>
using namespace std;
int Array [10] =  { 4,3,6,36,7,64,7,23,67,2 };
int Array2[10] = { 4,3,6,36,7,64,7,23,67,2 };
int Array3[10] = { 4,3,6,36,7,64,7,23,67,2 };
int Array4[10] = { 4,3,6,36,7,64,7,23,67,2 };
int Array5[10] = { 4,3,6,36,7,64,7,23,67,2 };
void Select_Sort(int AA[], int Num)
{cout << "原: ";copy(Array, Array + 10, ostream_iterator<int>(cout, "  "));cout << endl;bool Sorted = true;int mi, Temp;int Count = 0;for (int i = 0; i < Num; i++){mi = i;for (int j = i + 1; j < Num; j++){Count++;if (AA[mi] < AA[j])mi = j;}if (mi != i){Temp = AA[mi];AA[mi] = AA[i];AA[i] = Temp;}}printf("Select_sort******  %d  *******\n", Count);copy(AA, AA + 10, ostream_iterator<int>(cout, "  "));cout << endl << endl << endl;
}void Bubble_Sort(int AA[], int Num)
{cout << "原: ";copy(Array2, Array2 + 10, ostream_iterator<int>(cout, "  "));cout << endl;int Temp, Count = 0;bool Sorted = true;while (Sorted){Sorted = false;for (int i = 1; i < Num; i++){Count++;if (AA[i] > AA[i - 1]){Sorted = true;Temp = AA[i];AA[i] = AA[i - 1];AA[i - 1] = Temp;}}Num--;}printf("Bubble_sort******  %d  *******\n", Count);copy(AA, AA + 10, ostream_iterator<int>(cout, "  "));cout << endl << endl << endl;
}
void Insert_Sort(int AA[], int Num)
{cout << "原: ";copy(Array3, Array3 + 10, ostream_iterator<int>(cout, "  "));cout << endl;int Count = 0;for (int i = 1; i < Num; i++){int j = i - 1;int Temp = AA[i];while (j >= 0 && AA[j] < Temp){Count++;AA[j + 1] = AA[j];j--;}AA[j + 1] = Temp;}printf("Insert_sort******  %d  *******\n", Count);copy(AA, AA + 10, ostream_iterator<int>(cout, "  "));cout << endl << endl << endl;
}//记录并归排序时间复杂度的变量
int Count = 0;void Merge(int lo,int mi, int hi)
{int *AA = Array4 + lo;int Ib = mi - lo;int Ic = hi - mi;int* BB = new int[Ib];int* CC = Array4 + mi;int i = 0, j = 0, k = 0;for (int i = 0; i < Ib; i++){BB[i] = AA[i];Count++;}while (j < Ib && k < Ic){AA[i++] = BB[j] > CC[k] ? BB[j++] : CC[k++];Count++;}while (j < Ib){AA[i++] = BB[j++];Count++;}while (k < Ic){AA[i++] = CC[k++];Count++;}}void Merge_Sort(int lo,int hi)
{if (hi - lo < 2)return;int mi = (lo + hi) >> 1;Merge_Sort(lo, mi);Merge_Sort(mi, hi);Merge(lo, mi, hi);
}//记录快速排序时间复杂度的变量int Count2 = 0;int FindPos(int* AA, int lo, int hi)
{int Val = AA[lo];while (lo < hi){Count2++;while (lo < hi && AA[hi] <= Val){hi--;Count2++;}AA[lo] = AA[hi];while (lo < hi && AA[lo] >= Val){lo++;Count2++;}AA[hi] = AA[lo];}AA[lo] = Val;return lo;
}void Quick_Sort(int* AA, int lo, int hi)
{int Pos;if (lo < hi){Pos = FindPos(Array5, lo, hi);Quick_Sort(AA, lo, Pos - 1);Quick_Sort(AA, Pos + 1, hi);}
}int main(void)
{Select_Sort(Array, 10);Bubble_Sort(Array2, 10);Insert_Sort(Array3, 10);cout << "原: ";copy(Array4, Array4 + 10, ostream_iterator<int>(cout, "  "));cout << endl;Merge_Sort(0, 10);printf("Merge_sort******  %d  *******\n", Count);copy(Array4, Array4 + 10, ostream_iterator<int>(cout, "  "));cout << endl << endl << endl;cout << "原: ";copy(Array5, Array5 + 10, ostream_iterator<int>(cout, "  "));cout << endl;Quick_Sort(Array5, 0, 9);printf("Quick_sort******  %d  *******\n", Count2);copy(Array5, Array5 + 10, ostream_iterator<int>(cout, "  "));cout << endl << endl << endl;
}

测试结果如图:

测试结果为: 选择排序和冒泡排序的时间复杂度相同 大于插入排序和选择排序,小于并归排序。
总结:在该测试中插入排序法效率最高,并归排序法效率最低。

本篇到此结束。如果您发现本篇中有什么错误的地方麻烦您在评论区留言,谢谢!
如果遇到什么问题欢迎大家进群讨论或者加我qq
群内有各种学习资料,欢迎大家一起来学习!
本人qq:846581636
qq学习群:759252814
期待你的关注
感谢大家的支持,谢谢!

常见的五种排序,冒泡排序,选择排序,插入排序,并归排序,快速排序相关推荐

  1. 四种排序:选择,插入,冒泡,快速排序原理及其对应的时间、空间复杂度解析

    四种排序:选择,插入,冒泡,快速排序原理及其对应的时间空间复杂度 首先,在了解四种排序之前,让我们来了解一下什么是时间复杂度和空间复杂度. 时间复杂度:算法的时间复杂度是一个函数,它定性描述该算法的运 ...

  2. 网站优化基础教程:发布外链常见的五种方式!

    想要做好网站优化,外链的发布也是很重要的一环,如果您还没有做,建议您抓紧去做一下. 这篇文章发迹创业网就分享一下,常见的几种发布外链的方法. 1,锚文本 又叫做超链接,是指给关键词加一个链接,点击该关 ...

  3. Java数组去重的多种方法,[Java教程]JavaScript常见的五种数组去重的方式

    [Java教程]JavaScript常见的五种数组去重的方式 0 2016-12-14 15:00:17 ▓▓▓▓▓▓ 大致介绍 JavaScript的数组去重问题在许多面试中都会遇到,现在做个总结 ...

  4. 常见的五种神经网络(4)-深度信念网络(下)篇之深度信念网络的原理解读、参数学习

    该系列的其他文章: 常见的五种神经网络(1)-前馈神经网络 常见的五种神经网络(2)-卷积神经网络 常见的五种神经网络(3)-循环神经网络(上篇) 常见的五种神经网络(3)-循环神经网络(中篇) 常见 ...

  5. 常见的五种神经网络(3)-循环神经网络(上)篇

    转载请注明出处:https://thinkgamer.blog.csdn.net/article/details/100600661 博主微博:http://weibo.com/234654758 G ...

  6. 简析股票成交量常见的五种形态!

    简析股票成交量常见的五种形态! 一.放量,成交量比前一段时间明显放大的现象,分为相对放量和持续放量放量,上涨是一种比较好的形态. 二.缩量成交量比前一段时间明显缩减的现象.大部分投资者对市场未来走势的 ...

  7. JS 跨域问题常见的五种解决方式

    JS 跨域问题常见的五种解决方式 一.什么是跨域? 要理解跨域问题,就先理解好概念.跨域问题是由于javascript语言安全限制中的同源策略造成的. 简单来说,同源策略是指一段脚本只能读取来自同一来 ...

  8. html5 汽车广告,车身广告常见的五种制作方法

    原标题:车身广告常见的五种制作方法 车身广告能够在户外移动的展示广告信息,还能够给户外的环境添加一些惬意,让人不仅能看到车水马龙的交通,也能够欣赏到移动的广告画面.下面是对车身广告制作方法的详细介绍: ...

  9. 常见的五种神经网络(1)-前馈神经网络

    转载请注明出处:http://blog.csdn.net/gamer_gyt 博主微博:http://weibo.com/234654758 Github:https://github.com/thi ...

  10. 常见的五种HDMI接口类型,你知道多少?

    高清多媒体接口(High Definition Multimedia Interface)简称HDMI,是一种全数字化视频和声音发送接口,可以 同时发送未压缩的视频及音频信号 ,且发送时采用同一条线材 ...

最新文章

  1. 在IE6/7下表格td标签没有内容时不显示边框?
  2. IA-32系统编程指南 - 第三章 保护模式的内存管理【1】
  3. Vivado中set_clock_groups时钟约束的使用
  4. CCIE学习(7)——VLAN相关命令汇总
  5. medoo update mysql_Medoo Update的使用:修改更新数据
  6. Qt工作笔记-QCustomPlot让曲线动起来
  7. 第七章 Qt对象模型与容器类
  8. android studio一个页面等待3秒跳转_Flutter 对 iOS、Android(双端开发者)的快速理解(二)
  9. 汇编--查找第一个非0字符的五种方法
  10. 第一次学会!=EOF
  11. paip.提升安全性---防止敏感文件被下载
  12. 基于动力学前馈加反馈线性化的机器人动力学控制实现
  13. java中alt_eclipse中alt+/的作用
  14. 计算机房上课安全教育内容,机房实训安全教育学生须知
  15. 清华梦的粉碎—写给清华大学的退学申请 2005.9.22
  16. 环状二肽,82863-65-8,cyclo(Leu-Tyr)
  17. teamviewer linux远程开机,Ubuntu远程管理(teamviewer)
  18. 在Github上建立自己的个人博客网站详细教程
  19. 关于几个图像质量评价参数的计算总结
  20. Vmware虚拟机下三种网络模式配置

热门文章

  1. 【每天学点Python】案例三:BMR计算器
  2. 呕心整理Java中的12种常用设计模式以及应用场景
  3. 使用示波器学习变压器
  4. Android 实现FlowLayout流式布局(热门标签)
  5. exercise2 利雪
  6. google pay(谷歌支付) 开发者账号配置的坑
  7. 信息系统项目管理-项目成本管理-(七)
  8. 03 - 大学生如何使用GPT
  9. PC端无线连接打印机
  10. 【Kotlin】Android-使用WebDAV协议云存储文件(详细)—附demo源码