冒泡排序与快速排序

1、序言

ios开发中涉及到算法的地方还真不多,除非你的应用程序真的非常大,或者你想你的应用程序性能非常好才会去想到关于算法方面的性能优化,而在ios开发中真的能用得到的也就是关于排序的,当然如果你是做游戏的话那么你可能会涉及到不少的算法或者优化问题,但是这不是本篇文章讨论的范围。

后面的文章中,我将会给大家详细介绍八大算法。

2、冒泡排序

2.1 引出

前面的两篇博客里讲的插入排序是基于“逐个记录插入”,选择排序是基于“选择”,那么冒泡排序其实是基于“交换”。每次从第一个记录开始,一、二两个记录比较,大的往后放,二三两个记录比较...依次类推,这就是一趟冒泡排序。每一趟冒泡排序后,无序序列中值最大的记录冒到序列末尾,所以称之为冒泡排序。

2.2 代码

 //冒泡排序
 void bubbleSort(int *a,int n)
 {
     int i,j;
     ;i<n;i++)
         ;j<n-i+;j++){
             ]<a[j]){
                 a[j]=a[j]+a[j+];
                 a[j+]=a[j]-a[j+];
                 a[j]=a[j]-a[j+];
             }
         }
 }

冒泡排序算法:

 冒泡排序代码

  static void Main(string[] args)
         {
             ////五次比较
              ; i <= ; i++)
             {
                 List<int> list = new List<int>();
                 //插入2k个随机数到数组中
                 ; j < ; j++)
                 {
                     Thread.Sleep();
                     list.Add(, ));
                 }
                 Console.WriteLine("\n第" + i + "次比较:");
                 Stopwatch watch = new Stopwatch();
                 watch.Start();
                 var result = list.OrderBy(single => single).ToList();
                 watch.Stop();
                 Console.WriteLine("\n快速排序耗费时间:" + watch.ElapsedMilliseconds);
                 Console.WriteLine().ToList()));
                 watch.Start();
                 result = BubbleSort(list);
                 watch.Stop();
                 Console.WriteLine("\n冒泡排序耗费时间:" + watch.ElapsedMilliseconds);
                 Console.WriteLine().ToList()));
                 Console.ReadKey();
             }

       }

  //冒泡排序算法
         private static List<int> BubbleSort(List<int> list)
         {
             int temp;
             //第一层循环: 表明要比较的次数,比如list.count个数,肯定要比较count-1次
             ; i < list.Count - ;i++ )
             {
                 //list.count-1:取数据最后一个数下标,47
                 //j>i: 从后往前的的下标一定大于从前往后的下标,否则就超越了。
                 ; j > i;j-- )
                 {
                     //如果前面一个数大于后面一个数则交换
                     ] > list[j])
                     {
                         temp = list[j - ];
                         list[j - ] = list[j];
                         list[j] = temp;
                     }
                 }

             }
             return list;
         }

2.3 效率分析

相对于简单选择排序,冒泡排序交换次数明显更多。它是通过不断地交换把最大的数冒出来。冒泡排序平均时间和最坏情况下(逆序)时间为o(n^2)。最佳情况下虽然不用交换,但比较的次数没有减少,时间复杂度仍为o(n^2)。此外冒泡排序是稳定的。

3、快速排序

3.1 引出

快速排序是冒泡排序的一种改进,冒泡排序排完一趟是最大值冒出来了,那么可不可以先选定一个值,然后扫描待排序序列,把小于该值的记录和大于该值的记录分成两个单独的序列,然后分别对这两个序列进行上述操作。这就是快速排序,我们把选定的那个值称为枢纽值,如果枢纽值为序列中的最大值,那么一趟快速排序就变成了一趟冒泡排序。

3.2 代码

两种版本,第一种是参考《数据结构》,在网上这种写法很流行。第二种是参考《算法导论》,实现起来较复杂。

 //快速排序(两端交替着向中间扫描)
 void quickSort1(int *a,int low,int high)
 {
     int pivotkey=a[low];//以a[low]为枢纽值
     int i=low,j=high;
     if(low>=high)
         return;
     //一趟快速排序
     while(i<j){//双向扫描
         while(i < j && a[j] >= pivotkey)
             j--;
         a[i]=a[j];
         while(i < j && a[i] <= pivotkey)
             i++;
         a[j]=a[i];
     }
     a[i]=pivotkey;//放置枢纽值
     //分别对左边、右边排序
     quickSort1(a,low,i-);
     quickSort1(a,i+,high);
 }

 //快速排序(以最后一个记录的值为枢纽值,单向扫描数组)
 void quickSort2(int *a,int low,int high)
 {
     int pivotkey=a[high];//以a[high]为枢纽值
     ,temp,j;
     if(low>=high)
         return;
     //一趟快速排序
     for(j=low;j<high;j++){
         if(a[j]<=pivotkey){
             i++;
             temp=a[i];
             a[i]=a[j];
             a[j]=temp;
         }
     }
     i++;
     //放置枢纽值
     temp=a[i];
     a[i]=pivotkey;
     a[high]=temp;
     //分别对左边、右边排序
     quickSort2(a,low,i-);
     quickSort2(a,i+,high);
 }

快速排序算法:

 快速排序法

  static void Main(string[] args)
         {

             //5次比较
             ; i <= ; i++)
             {
                 List<int> list = new List<int>();
                 //插入200个随机数到数组中
                 ; j < ; j++)
                 {
                     Thread.Sleep();
                     list.Add(, ));
                 }
                 Console.WriteLine("\n第" + i + "次比较:");
                 Stopwatch watch = new Stopwatch();
                 watch.Start();
                 var result = list.OrderBy(single => single).ToList();
                 watch.Stop();
                 Console.WriteLine("\n系统定义的快速排序耗费时间:" + watch.ElapsedMilliseconds);
                 Console.WriteLine().ToList()));
                 watch.Start();
                 , list.Count - );
                 watch.Stop();
                 Console.WriteLine("\n俺自己写的快速排序耗费时间:" + watch.ElapsedMilliseconds);
                 Console.WriteLine().ToList()));
                 Console.ReadKey();
             }
         }

  public class QuickSortClass
     {

         ///<summary>
         ////// 分割函数
         ///</summary>
         //////<param name="list">待排序的数组</param>
         ///<param name="left">数组的左下标</param>
         //////<param name="right"></param>
         ///<returns></returns>
          public int Division(List<int> list, int left, int right)
          {
              //首先挑选一个基准元素
              int baseNum = list[left];
              while (left < right)
              {
                  //从数组的右端开始向前找,一直找到比base小的数字为止(包括base同等数)
                  while (left < right && list[right] >= baseNum)
                      right = right - ;
                  //最终找到了比baseNum小的元素,要做的事情就是此元素放到base的位置
                  list[left] = list[right];
                  //从数组的左端开始向后找,一直找到比base大的数字为止(包括base同等数)
                  while (left < right && list[left] <= baseNum)
                      left = left + ;
                  //最终找到了比baseNum大的元素,要做的事情就是将此元素放到最后的位置
                  list[right] = list[left];
              }
              //最后就是把baseNum放到该left的位置
              list[left] = baseNum;
              //最终,我们发现left位置的左侧数值部分比left小,left位置右侧数值比left大
              //至此,我们完成了第一篇排序
              return left;
          }
         public void QuickSort(List<int> list, int left, int right)
         {
             //左下标一定小于右下标,否则就超越了
             if (left < right)
             {
                 //对数组进行分割,取出下次分割的基准标号
                 int i = Division(list, left, right);
                 //对“基准标号“左侧的一组数值进行递归的切割,以至于将这些数值完整的排序
                 QuickSort(list, left, i - );
                 //对“基准标号“右侧的一组数值进行递归的切割,以至于将这些数值完整的排序
                 QuickSort(list, i + , right);
             }
         }
     }

3.3 效率分析

快速排序时间与划分是否对称有关。快速排序的平均时间复杂度为o(n*logn),至于为什么是o(n*logn),请参考《算法导论》第7章,书中用递归树的方法阐述了快速排序平均时间。且常数因子很小,所以就平均时间而言,快速排序是很好的内部排序方法。最佳情况下(每次划分都对称)时间复杂度o(n*logn)。最坏情况下(每次划分都不对称,如输入的序列有序或者逆序时)时间复杂度为o(n^2),所以在待排序序列有序或逆序时不宜选用快速排序。此外,快速排序是不稳定的。

最佳情况下,每次划分都是对称的,由于枢纽值不再考虑,所以得到的两个子问题的大小不可能大于n/2,同时一趟快速排序时间为o(n),所以运行时间递归表达式:

T(n)<=2T(n/2)+o(n)。这个递归式的解法请参考下一篇博客中归并排序效率分析。其解为T(n)=o(n*logn)。

最坏情况下,每次划分都很不对称,T(n)=T(n-1)+o(n),可以用递归树来解,第i层的代价为n-i+1.总共有n层。把每一层代价加起来有n-1个n相加。所以这个递归式的解为T(n)=o(n^2),此时就是冒泡排序。

ios开发——常用经典算法OC篇&冒泡/快速的更多相关文章

  1. iOS开发——高级技术精选OC篇&Runtime之字典转模型实战

    Runtime之字典转模型实战 如果您还不知道什么是runtime,那么请先看看这几篇文章: http://www.cnblogs.com/iCocos/p/4734687.html http://w ...

  2. iOS开发--JS调用原生OC篇

    JS调用原生OC篇 方式一(反正我不用) 第一种方式是用JS发起一个假的URL请求,然后利用UIWebView的代理方法拦截这次请求,然后再做相应的处理. 我写了一个简单的HTML网页和一个btn点击 ...

  3. iOS开发——网络使用技术OC篇&网络爬虫-使用正则表达式抓取网络数据

    网络爬虫-使用正则表达式抓取网络数据 关于网络数据抓取不仅仅在iOS开发中有,其他开发中也有,也叫网络爬虫,大致分为两种方式实现 1:正则表达 2:利用其他语言的工具包:java/Python 先来看 ...

  4. iOS开发——高级UI之OC篇&UIdatePicker&UIPickerView简单使用

    UIdatePicker&UIPickerView简单使用 /***************************************************************** ...

  5. iOS开发-常用第三方开源框架介绍

    iOS开发-常用第三方开源框架介绍 图像: 1.图片浏览控件MWPhotoBrowser        实现了一个照片浏览器类似 iOS 自带的相册应用,可显示来自手机的图片或者是网络图片,可自动从网 ...

  6. IOS开发常用设计模式

    IOS开发常用设计模式 说起设计模式,感觉自己把握不了笔头,所以单拿出iOS开发中的几种常用设计模式谈一下. 单例模式(Singleton) 概念:整个应用或系统只能有该类的一个实例 在iOS开发我们 ...

  7. javascript常用经典算法实例详解

    javascript常用经典算法实例详解 这篇文章主要介绍了javascript常用算法,结合实例形式较为详细的分析总结了JavaScript中常见的各种排序算法以及堆.栈.链表等数据结构的相关实现与 ...

  8. iOS开发--常用技巧 (MJRefresh详解)

         iOS开发--常用技巧 (MJRefresh详解) https://github.com/CoderMJLee/MJRefresh 下拉刷新01-默认 self.tableView.head ...

  9. iOS开发常用第三方库

    UI 动画 网络相关 Model 其他 数据库 缓存处理 PDF 图像浏览及处理 摄像照相视频音频处理 响应式框架 消息相关 版本新API的Demo 代码安全与密码 测试及调试 AppleWatch ...

随机推荐

  1. ArcMap自定义脚本工具制作

    原文 ArcMap自定义脚本工具制作 在制图的前期,一般需要做一些数据的整理,如图层合并.裁剪等工作.虽然在ArcMap中也有提供对应的工具,但使用起来需要点技巧.如批量裁剪,虽然可以实现,但出来的结 ...

  2. mybatis实战教程(mybatis in action)之九:mybatis 代码生成工具的使用

    mybatis 应用程序,需要大量的配置文件,对于一个成百上千的数据库表来说,完全手工配置,这是一个很恐怖的工作量. 所以mybatis 官方也推出了一个mybatis代码生成工具的jar包. 今天花 ...

  3. [原创]C语言利用pcre正则表达式库

    C语言使用正则表达式,可以利用pcre库,这个比较不错的哦. 在使用过程中,利用python进行测试正则表达式是否OK,后发现出现了问题.如下所示: regex.c:11:18: warning: u ...

  4. 【windows核心编程】一个HOOK的例子

    一.应用场景 封装一个OCX控件,该控件的作用是来播放一个视频文件,需要在一个进程中放置四个控件实例. 由于控件是提供给别人用的,因此需要考虑很多东西. 二.考虑因素 1.控件的父窗口resize时需 ...

  5. IOS-day02_OC中类的声明

    在上一个笔记中类的使用中,在编译链接的时候会有警告,原因就是我们没有对类进行声明 类的声明如下:使用关键字@interface #import <Foundation/Foundation.h& ...

  6. 在asp.net mvc中使用PartialView返回部分HTML段

    问题链接: MVC如何实现异步调用输出HTML页面 该问题是个常见的 case, 故写篇文章用于提示新人. 在asp.net mvc中返回View时使用的是ViewResult,它继承自ViewRes ...

  7. (转载)OC学习篇之---类的初始化方法和点语法的使用

    昨天介绍了OC中类的定义和使用,今天我们来继续学习类的初始化方法和点语法的使用. 一.首先来看一下类的初始化方法 在Java中我们知道一个每个类都有构造方法,这里的初始化方法就是和构造方法一个概念的, ...

  8. git常用命令[持续更新]

    git commit -am "abc" 提交已经删除过的文件 git reset --hard HEAD 用于清除跟踪文件的修改

  9. JAVA中的常见面试题1

    1.线程同步的方法的使用. sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要捕捉InterruptedException异常. wait():使一个线程处于等待状态,并且 ...

  10. SpringMVC学习笔记

    1.严格实现MVC设计思想的框架,严格分层,减少耦合: 2.组件(红色必需) 2.1 DispatcherServlet 前端控制器 2.2 Controller 业务控制器 2.3 Handler ...