在上面一篇博客当中,我们发现普通查找和排序查找的性能差别很大。作为一个100万的数据,如果使用普通的查找方法,那么每一个数据查找平均下来就要几十万次,那么二分法的查找呢,20多次就可以搞定。这中间的差别是非常明显的。既然排序有这么好的效果,那么这篇博客中,我们就对排序算做一个总结。

按照我个人的理解,排序可以分为两种:一种是非递归排序,它主要按照非递归的方法对数据进行排序,也就是说主要数据的移位和循环来完成;另外一种就是递归方法,我们在排列当前数据的时候首先把子数据排列有序,然后才会排列当前的数据。这种不断递归调用的方法就是递归排序。

非递归排序的方法很多,这里主要介绍冒泡排序、插入排序、希尔排序;递归的方法也不少,这里介绍的方法是快速排序、归并排序和堆排序。排序的内容很多,本篇博客主要介绍非递归排序,递归排序的内容主要在下一节内容解决。

(1)冒泡排序

冒泡排序的内容并不复杂。假设有n个数据需要排序,那么我们需要确定n个从大到小的数据,每一次都挑选第n大的数据是多少,并且放大相应的位置。直到所有的数据都排列整齐了,那么我们的排序就结束了。

  1. void bubble_sort(int array[], int length)
  2. {
  3. int inner = 0, outer = 0;
  4. int median = 0;
  5. if(NULL == array || 0 == length)
  6. return;
  7. for(outer = length-1; outer >= 1; outer --){
  8. for(inner = 0; inner < outer; inner ++){
  9. if(array[inner] > array[inner + 1]){
  10. median = array[inner];
  11. array[inner] = array[inner + 1];
  12. array[inner + 1] = median;
  13. }
  14. }
  15. }
  16. }
void bubble_sort(int array[], int length)
{
int inner = 0, outer = 0;
int median = 0; if(NULL == array || 0 == length)
return; for(outer = length-1; outer >= 1; outer --){
for(inner = 0; inner < outer; inner ++){
if(array[inner] > array[inner + 1]){
median = array[inner];
array[inner] = array[inner + 1];
array[inner + 1] = median;
}
}
}
}

那么这个程序有没有什么改进的地方呢?当然存在,如果发现在一次遍历循环之中,如果没有发生移位的现象,那么是不是可以判断这个排序可以结束了呢?朋友们可以好好思考一下这个问题?

  1. void bubble_sort(int array[], int length)
  2. {
  3. int inner = 0, outer = 0;
  4. int median = 0;
  5. int flag = 1;
  6. if(NULL == array || 0 == length)
  7. return;
  8. for(outer = length-1; outer >= 1 && flag; outer --){
  9. flag = 0;
  10. for(inner = 0; inner < outer; inner ++){
  11. if(array[inner] > array[inner + 1]){
  12. median = array[inner];
  13. array[inner] = array[inner + 1];
  14. array[inner + 1] = median;
  15. if(flag == 0)
  16. flag = 1;
  17. }
  18. }
  19. }
  20. }
void bubble_sort(int array[], int length)
{
int inner = 0, outer = 0;
int median = 0;
int flag = 1; if(NULL == array || 0 == length)
return; for(outer = length-1; outer >= 1 && flag; outer --){
flag = 0; for(inner = 0; inner < outer; inner ++){
if(array[inner] > array[inner + 1]){
median = array[inner];
array[inner] = array[inner + 1];
array[inner + 1] = median; if(flag == 0)
flag = 1;
}
}
}
}

(2) 插入排序

插入排序的意思就是说,我们把数据分成两个部分,一部分是已经排好序的数据,一部分是当前还没有完成排序的数据。那么这么说来的话,排序的过程是不是就是把没有排序的数据逐个插入到已经排好序的队列中的过程呢。大家可以自己先试一下,然后再看看我的代码对不对?

  1. void insert_sort(int array[], int length)
  2. {
  3. int inner = 0;
  4. int outer = 0;
  5. int median = 0;
  6. if(NULL == array || 0 == length)
  7. return;
  8. for(outer = 1; outer <length; outer ++){
  9. for(inner = outer; inner >= 1; inner --){
  10. if(array[inner] < array[inner -1]){
  11. median = array[inner];
  12. array[inner] = array[inner -1];
  13. array[inner -1] = median;
  14. }else{
  15. break;
  16. }
  17. }
  18. }
  19. }
void insert_sort(int array[], int length)
{
int inner = 0;
int outer = 0;
int median = 0;
if(NULL == array || 0 == length)
return; for(outer = 1; outer <length; outer ++){
for(inner = outer; inner >= 1; inner --){
if(array[inner] < array[inner -1]){
median = array[inner];
array[inner] = array[inner -1];
array[inner -1] = median;
}else{
break;
}
}
}
}

那么插入排序有没有像冒泡排序那样的改进方法呢?其实没有。因为每一次插入排序的位置都是局部比较的结果,而冒泡排序每一次的内容都是全局最优的。这从数据比较的次数就可以看出来。

(3)希尔排序

希尔排序,我个人认为可以看成是冒泡排序的变种。它的基本思想是:首先按照一个序列递减的方法逐渐进行排序。比如说有10个数据,我们按照序列5、3、1的顺序进行排序。首先是5,那么我们对1和6、2和7、3和8、4和9、5和10进行排列;第二轮是3,那么对数据1、4、7、10排列,再对2、5、8进行排列,以及3、6、9排列;第三轮就和冒泡排序一样了,以此对每个数据进行排列。它的优势就是让整个队列基本有序,减少数据移动的次数,从而降低算法的计算复杂度。

  1. void shell_sort(int array[], int length, int step)
  2. {
  3. int inner = 0;
  4. int outer = 0;
  5. int median = 0;
  6. if(NULL == array || 0 == length)
  7. return;
  8. for(; step >= 1; step -=2){
  9. for(int index = 0; index < step; index ++){
  10. if((length -1) < (index + step))
  11. continue;
  12. else{
  13. outer = index + step;
  14. while( (outer + step) <= (length - 1))
  15. outer += step;
  16. }
  17. for(;  outer >= (index + step);  outer -= step){
  18. for(inner = index; inner <= outer - step; inner += step){
  19. if(array[inner] >= array[inner + step]){
  20. median = array[inner];
  21. array[inner] = array[inner + step];
  22. array[inner + step] = median;
  23. }
  24. }
  25. }
  26. }
  27. }
  28. }
void shell_sort(int array[], int length, int step)
{
int inner = 0;
int outer = 0;
int median = 0; if(NULL == array || 0 == length)
return; for(; step >= 1; step -=2){
for(int index = 0; index < step; index ++){
if((length -1) < (index + step))
continue;
else{
outer = index + step;
while( (outer + step) <= (length - 1))
outer += step;
} for(; outer >= (index + step); outer -= step){
for(inner = index; inner <= outer - step; inner += step){
if(array[inner] >= array[inner + step]){
median = array[inner];
array[inner] = array[inner + step];
array[inner + step] = median;
}
}
}
}
}
}

总结:

(1)上面的排序都是非递归程序,理解上不难,但是细节问题需要注意,特别是长度的问题

(2)代码编写的时候务必注意测试用例的设计

(3)如果可能的情况下,多使用已经验证的代码和函数

c++(非递归排序)的更多相关文章

  1. C#实现(递归和非递归)高速排序和简单排序等一系列排序算法

        本人由于近期工作用到了一些排序算法.就把几个简单的排序算法.想冒泡排序,选择排序,插入排序.奇偶排序和高速排序等整理了出来,代码用C#代码实现,而且通过了測试.希望能给大家提供參考.     ...

  2. 笔试算法题(56):快速排序实现之非递归实现,最小k值选择(non-recursive version, Minimal Kth Selection of Quick Sort)

    议题:快速排序实现之五(非递归实现,短序列优先处理,减少递归栈大小) 分析: 算法原理:此算法实现适用于系统栈空间不足够快速排序递归调用的需求,从而使用非递归实现快速排序算法:使用显示下推栈存储快速排 ...

  3. 排序算法练习--JAVA(插入、直接选择、冒泡、快速排序、非递归快速排序)

    排序算法是数据结构中的经典算法知识点,也是笔试面试中经常考察的问题,平常学的不扎实笔试时候容易出洋相,回来恶补,尤其是碰到递归很可能被问到怎么用非递归实现... package sort; impor ...

  4. 排序算法C语言实现——快速排序的递归和非递归实现

    /*快排 -  递归实现nlogn*//*原理:    快速排序(Quicksort)是对冒泡排序的一种改进.    快速排序由C. A. R. Hoare在1962年提出.它的基本思想是:通过一趟排 ...

  5. 合并两个排序的链表递归和非递归C++实现

    题目描述: 输入两个单调递增的链表,输出两个链表合成后的链表,要求合成后的链表满足单调不减规则. 1.分析 已知输入的两个链表递增有序,要使输出的链表依然递增有序,可以依次从输入的两个链表中挑选最小的 ...

  6. java:合并两个排序的链表(递归+非递归)

    //采用不带头结点的链表 非递归实现 public static ListNode merge(ListNode list1,ListNode list2){ if(list1==null) retu ...

  7. 先贴上代码:Random快排,快排的非递归实现

    设要排序的数组是A[0]……A[N-1],首先任意选取一个数据(通常选用数组的第一个数)作为主元,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序.值得注意的是, ...

  8. javascript实现非递归--归并排序

    另一道面试题是实现归并排序,当然,本人很不喜欢递归法,因为递归一般都是没有迭代法好.所以首选都是用迭代法,但是迭代法确实是难做啊,至底而上的思想不好把握. 这是我的实现代码 /* * * 非递归版归并 ...

  9. 深度优先搜索(DFS)递归形式改为非递归形式

    DFS将递归改为非递归这个方法的需求来自于一道三维积木组合的题目,还在苦苦调试中,暂且不提. 普通的认识对于递归向非递归的转化无非是使用栈,但是结合到深度搜索如何将栈很好利用,如何很好保存现场,都不是 ...

随机推荐

  1. [HDU - 5170GTY's math problem 数的精度类

    题目链接:HDU - 5170GTY's math problem 题目描述 Description GTY is a GodBull who will get an Au in NOI . To h ...

  2. ReactNative实现图集功能

    需求描述: 图片缩放.拖动.长按保存等基础图片查看的功能: 展示每张图片文本描述: 实现效果,如图: 实现步骤 使用第三方插件:react-native-image-zoom-viewer 插件Git ...

  3. mysql case when group by实例

    mysql 中类似php switch case 的语句. select xx字段, case 字段 when 条件1 then 值1 when 条件2 then 值2 else 其他值 END 别名 ...

  4. zepto的返回顶部scrollTop的动画解决方法

    写移动端的时候,引入的zepto.js里的animate不包括scrollTop,所以返回顶部的时候,没有动画的效果.这里我使用的是setInterval的方法.代码详情如下 <!DOCTYPE ...

  5. asp.net core webapi 服务端配置跨域

    在前后端分离开发中服务端仅仅只为前端提供api接口,并且前后端往往单独部署,此时就会出现浏览器跨域问题.asp.net core提供了简单优雅的解决方案. 在startup文件的Configure添加 ...

  6. Keras 学习之旅(一)

    软件环境(Windows): Visual Studio Anaconda CUDA MinGW-w64 conda install -c anaconda mingw libpython CNTK ...

  7. 在vim中使用zencoding/Emmet

    zencoding在vim上的插件已经改名为Emmet.vim 1. 安装,推荐使用vundle插件管理器安装,在~/.vimrc中,添加:Bundle 'Emmet.vim',输入命令vim +Bu ...

  8. JSP的三种注释方式

    HTML注释(输出注释):指在客户端查看源代码时能看见注释.例如, <!-- this is an html comment.it will show up int the response. ...

  9. Jenkins远程部署SpringBoot应用

    一般Web工程通过Jenkins远程部署到Tomcat,可以采用Maven的tomcat-maven-plugin插件进行部署.最近接触到Spring Boot工程的部署,由于Spring Boot应 ...

  10. Md2All

    微信公众号:颜家大少欢迎关注我,一起学习,一起进步!目前,知到 Md2All 的朋友还很少,如果你觉得有帮助,希望能告诉身边有需要的朋友. 谢谢! Md2All 简介 一个Markdown在线转换工具 ...