冒泡排序与快速排序

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. Oracle 存储过程的创建,及触发器调用存储过程

    一.创建存储过程 1.存储过程写法 create or replace procedure HVM_BYQ_TJ --变压器统计信息--->入库 (id in number) as begin ...

  2. Ubuntu 出现 apt-get问题的解决方法

    ubuntu 10.10 sudo apt-get update 404  Not Found or W: Failed to fetch http://cn.old-releases.ubuntu. ...

  3. 一个FragmentActivity多个Fragment的生命周期事件记录

    初次打开FragmentActivity时 VisitTaskManagerActivity(): onCreate VisitTaskManagerActivity(): onStart Visit ...

  4. C++ 出现bug :二位数组的操作运算,求非对角线的元素的和

    编写一个通用程序,求出二位数组(行数和列数必须相等)的非对角线的元素之和,试建立类MATRIX完成上述功能 #include<iostream> using namespace std; ...

  5. bzoj 1778 [Usaco2010 Hol]Dotp 驱逐猪猡(高斯消元)

    [题意] 炸弹从1开始运动,每次有P/Q的概率爆炸,否则等概率沿边移动,问在每个城市爆炸的概率. [思路] 设M表示移动一次后i->j的概率.Mk为移动k次后的概率,则有: Mk=M^k 设S= ...

  6. Google Accounts,OpenID,OAuth

    App Engine以与Google Accounts的集成为其特色.Google Accounts是被Google应用程序如:Google Mail.Google Docs.Google Calen ...

  7. 如何学习java ee

    来看看Sun给出的J2EE 相关技术主要分为几大块. 1. Web Service技术 -  Java API for XML Processing (JAXP) -  Java API for XM ...

  8. unix文件权限

    一.UNIX下关于文件权限的表示方法和解析 SUID 是 Set User ID, SGID 是 Set Group ID的意思. UNIX下可以用ls -l 命令来看到文件的权限.用ls命令所得到的 ...

  9. Homework-10 the Enhanced Version

    经过一周对于JavaScript HTML语言等相关知识的学习,我终于基本完成了作业的要求,也是实现了我原先计划的第二部,推出了加强版的Homework-10 他由3个HTML组成,JS脚本直接选择嵌 ...

  10. Struts2 文件上传

    一:表单准备 ① 要想使用HTML 表单上传一个或多个文件     –须把 HTML表单的 enctype属性设置为multipart/form-data     –须把HTML 表单的method ...