漫步IOS--部分排序一:冒泡排序、选择排序和快速排序
2014-12-26 14:39
309 查看
1 冒泡排序
冒泡排序的思路:从序列的一头开始,每次比较相邻的两个数,将大的往后移.当走到序列结尾的时候,最后一个即是最大的;然后再从头开始比较,只是这次比较到倒数第二个就好,因为最后一个已经确定是最大了。如此往复,直到没有需要比较的元素为止。个人表述有限,可参考维基百科介绍。
参考代码:
时间复杂度:
冒泡排序一般是作为程序员入门算法进行讨论的,因为他的效率着实有些低。别的不说,相比选择排序就落好几条街。
最好时间复杂度是O(n);
这种情况是: 6 , 1, 2, 3, 4, 5, 类似吧。即只需一趟即可把顺序完全排好。出现的概率有点儿低。
最坏时间复杂度是O(n2);
这种情况是:6,5,4,3,2,1类似吧,即每一趟的每一次比较都需要进行数据交换。对此不予评论。
2 选择排序
选择排序的思路:每一趟扫描选取剩下的元素中一个最大的放在后边。他与冒泡排序的区别在于,在扫描的过程中,只是保留选中元素的下标,而并不是将元素进行位移。更换选中的数据也只是更换一下下标的值,中间不会产生数据移动。所以在效率上会高很多很多。
参考代码
时间复杂度:
比较次数O(n2),交换次数O(n),因为在计算机中交换的CPU时间需要的比比较所需要的CPU时间要长的多,所以选择排序比冒泡排序要快许多。最好情况是,已经有序,交换0次;最坏情况是,逆序,交换n-1次。
3 快速排序
快速排序的思路:在序列中选择一个标杆,通常选择序列的第一个数,然后对序列中的数从两头开始,将小于他的数放在左边,大于他的数放在他右边。这时以这个数为标杆,分成了左右两块,左边的都小于他,右边的都大于他。然后再递归调用,直到没有可排序的。即只有两个元素。感觉不大容易看懂,所以贴了一个动图来看看。
算法思路:我贴一下百度的讲解吧。
假设用户输入了如下数组:
创建变量i=0(指向第一个数据), j=5(指向最后一个数据), k=6(赋值为第一个数据的值)。
我们取走了下标0的数据,于是,我们需要找到一个数字来替换他。由于我们要把所有比6小的数移动到左面,所以我们可以开始寻找比6小的数并从右往左找。别急,我们要按顺序找哦。不断递减j的值,我们发现下标3的数据比6小,于是把3移到下标0(实际是i指向的位置。代码中要用i,因为后面还会循环这个步骤,不用i的话第二次循环:
i=0 j=3 k=6
由于变量k已经储存了下标0的数据,所以我们可以放心的把下标0覆盖了。如此一来,下标3虽然有数据,但是相当于没有了,因为数据已经复制到别的地方了。于是我们再找一个数据来替换他。这次要变成找比k大的了,而且要从前往后找了。递加变量i,发现下标2是第一个比k大的,于是用下标2的数据7替换j指向的下标3的数据,数据状态变成下表:
i=2 j=3 k=6
重复上面的步骤,递减变量j。这时,我们发现i和j“碰头”了:他们都指向了下标2。于是,循环结束,把k填回下标2里,即得到结果。
填回k之后状态为:
如果i和j没有碰头的话,就递加i找大的,还没有,就再递减j找小的,如此反复,不断循环。注意判断和寻找是同时进行的。
注意:快速排序不会直接得到最终结果,只会把比k大和比k小的数分到k的两边。(你可以想象一下i和j是两个机器人,数据就是大小不一的石头,先取走i前面的石头留出回旋的空间,然后他们轮流分别挑选比k大和比k小的石头扔给对面,最后在他们中间把取走的那块石头放回去,于是比这块石头大的全扔给了j那一边,小的全扔给了i那一边。只是这次运气好,扔完一次刚好排整齐。)为了得到最后结果,需要再次对下标2两边的数组分别执行此步骤,然后再分解数组,直到数组不能再分解为止(只有一个数据),才能得到正确结果。
参考代码:
时间复杂度:
快速排序是面试题中经常会提到的排序算法之一。也是最容易让人产生忘性的,建议多敲几遍加强一下记忆。
最差时间复杂度:O(n2)
最好时间复杂度:O(nlogn)
今天写的匆忙,后面会再修改更新。
冒泡排序的思路:从序列的一头开始,每次比较相邻的两个数,将大的往后移.当走到序列结尾的时候,最后一个即是最大的;然后再从头开始比较,只是这次比较到倒数第二个就好,因为最后一个已经确定是最大了。如此往复,直到没有需要比较的元素为止。个人表述有限,可参考维基百科介绍。
参考代码:
//冒泡排序 void sortUp(int arr[],int size){ for (int i = 0; i < size ; i++) { for (int j = size-1; j > i; j--) { if(arr[i] > arr[j]){ arr[i] += arr[j]; arr[j] = arr[i] - arr[j]; arr[i] = arr[i] - arr[j]; } } } }
时间复杂度:
冒泡排序一般是作为程序员入门算法进行讨论的,因为他的效率着实有些低。别的不说,相比选择排序就落好几条街。
最好时间复杂度是O(n);
这种情况是: 6 , 1, 2, 3, 4, 5, 类似吧。即只需一趟即可把顺序完全排好。出现的概率有点儿低。
最坏时间复杂度是O(n2);
这种情况是:6,5,4,3,2,1类似吧,即每一趟的每一次比较都需要进行数据交换。对此不予评论。
2 选择排序
选择排序的思路:每一趟扫描选取剩下的元素中一个最大的放在后边。他与冒泡排序的区别在于,在扫描的过程中,只是保留选中元素的下标,而并不是将元素进行位移。更换选中的数据也只是更换一下下标的值,中间不会产生数据移动。所以在效率上会高很多很多。
参考代码
//选择排序 void sortSelect(int arr[],int size){ int re[size]; for (int i = 0; i < size; i++) { int min = i; for (int j = i+1; j < size; j++) { if (arr[min] > arr[j]) { min = j; } } if(min != i){ arr[i] += arr[j]; arr[j] = arr[i] - arr[j]; arr[i] = arr[i] - arr[j]; } } }
时间复杂度:
比较次数O(n2),交换次数O(n),因为在计算机中交换的CPU时间需要的比比较所需要的CPU时间要长的多,所以选择排序比冒泡排序要快许多。最好情况是,已经有序,交换0次;最坏情况是,逆序,交换n-1次。
3 快速排序
快速排序的思路:在序列中选择一个标杆,通常选择序列的第一个数,然后对序列中的数从两头开始,将小于他的数放在左边,大于他的数放在他右边。这时以这个数为标杆,分成了左右两块,左边的都小于他,右边的都大于他。然后再递归调用,直到没有可排序的。即只有两个元素。感觉不大容易看懂,所以贴了一个动图来看看。
算法思路:我贴一下百度的讲解吧。
假设用户输入了如下数组:
下标 | 0 | 1 | 2 | 3 | 4 | 5 |
数据 | 6 | 2 | 7 | 3 | 8 | 9 |
我们取走了下标0的数据,于是,我们需要找到一个数字来替换他。由于我们要把所有比6小的数移动到左面,所以我们可以开始寻找比6小的数并从右往左找。别急,我们要按顺序找哦。不断递减j的值,我们发现下标3的数据比6小,于是把3移到下标0(实际是i指向的位置。代码中要用i,因为后面还会循环这个步骤,不用i的话第二次循环:
下标 | 0 | 1 | 2 | 3 | 5 | 5 |
数据 | 3 | 2 | 7 | 3 | 8 | 9 |
由于变量k已经储存了下标0的数据,所以我们可以放心的把下标0覆盖了。如此一来,下标3虽然有数据,但是相当于没有了,因为数据已经复制到别的地方了。于是我们再找一个数据来替换他。这次要变成找比k大的了,而且要从前往后找了。递加变量i,发现下标2是第一个比k大的,于是用下标2的数据7替换j指向的下标3的数据,数据状态变成下表:
下标 | 0 | 1 | 2 | 3 | 4 | 5 |
数据 | 3 | 2 | 7 | 7 | 8 | 9 |
重复上面的步骤,递减变量j。这时,我们发现i和j“碰头”了:他们都指向了下标2。于是,循环结束,把k填回下标2里,即得到结果。
填回k之后状态为:
下标 | 0 | 1 | 2 | 3 | 4 | 5 |
数据 | 3 | 2 | 6 | 7 | 8 | 9 |
注意:快速排序不会直接得到最终结果,只会把比k大和比k小的数分到k的两边。(你可以想象一下i和j是两个机器人,数据就是大小不一的石头,先取走i前面的石头留出回旋的空间,然后他们轮流分别挑选比k大和比k小的石头扔给对面,最后在他们中间把取走的那块石头放回去,于是比这块石头大的全扔给了j那一边,小的全扔给了i那一边。只是这次运气好,扔完一次刚好排整齐。)为了得到最后结果,需要再次对下标2两边的数组分别执行此步骤,然后再分解数组,直到数组不能再分解为止(只有一个数据),才能得到正确结果。
参考代码:
//快速排序 void sortQuickly(int arr[],int low,int high){ //m代表前面的标记,n代表后面的标记。L表示当前的中间位 int m = low,n = high; int temp = arr[low]; if (low < high) { while(m < n){ while((arr >= temp) && (m < n)){ n--; } arr[m] = arr ; while((arr[m] <= temp) && (m < n)){ m++; } arr = arr[m]; } arr = temp; sortQuickly(arr,low,m-1); sortQuickly(arr,n+1,high); }else{ return; } }
时间复杂度:
快速排序是面试题中经常会提到的排序算法之一。也是最容易让人产生忘性的,建议多敲几遍加强一下记忆。
最差时间复杂度:O(n2)
最好时间复杂度:O(nlogn)
今天写的匆忙,后面会再修改更新。
相关文章推荐
- 简单的排序算法——插入排序,选择排序,交换排序(冒泡排序,快速排序)
- 排序--选择排序,插入排序,冒泡排序,shell排序,快速排序(递归,迭代,改进版本),归并排序
- java实现冒泡排序,选择排序,插入排序,快速排序(简洁版)及性能测试
- 冒泡排序,选择排序,快速排序
- C#实现所有经典排序算法(选择排序 冒泡排序 快速排序)
- 黑马程序员----Java中几种常用排序算法(选择排序、冒泡排序、快速排序)
- 冒泡排序,选择排序,插入排序,快速排序(PHP)
- 内部排序冒泡排序、插入排序、选择排序、快速排序的算法和PHP实现
- 冒泡排序,选择排序,插入排序,快速排序的简单性能测试
- C#实现所有经典排序算法(选择排序 冒泡排序 快速排序)
- 算法导论之插入排序,选择排序,归并排序,冒泡排序,希尔排序,堆排序,快速排序的c语言实现
- 8 排序--选择排序,插入排序,冒泡排序,shell排序,快速排序(递归,迭代,改进版本),归并排序
- 简单的排序算法——插入排序,选择排序,交换排序(冒泡排序,快速排序)
- 冒泡排序与选择排序的不同、快速排序与选择排序的结合
- Java排序算法(冒泡排序、选择排序、插入排序、反数组排序、快速排序)例子
- 简单的排序算法——插入排序,选择排序,交换排序(冒泡排序,快速排序)
- 冒泡排序与选择排序的不同、快速排序与选择排序的结合
- 数据结构与算法:七种排序算法总结(冒泡排序、选择排序、直接插入排序、希尔排序、堆排序、归并排序、快速排序)
- PHP实现插入排序,选择排序,冒泡排序和快速排序
- java实现冒泡排序,选择排序,插入排序,快速排序(简洁版)及性能测试