关于快速排序
来源:互联网 发布:java开发人员培训机构 编辑:程序博客网 时间:2024/04/27 16:37
今天在做leetcode的过程中用到了快排,于是自己写了一个。但是发现一些细节上的错误会导致整个程序的错误。
话不多说先贴错误代码
private void quickSort(int[] c , int low , int high){ if(c.length == 0||c.length==1||low>=high) return; int mid = part(c, low, high); quickSort(c, low , mid-1); quickSort(c , mid+1, high); } private int part(int[] c , int low , int high){ int i = low; int j = high; while(true){ while(c[++i] >= c[low]){ if(i == high) break; } while(c[j] < c[low]){ j--; if(j == low ) break; } swap(c,i,j); if( i > j) break; } swap(c,low,j); return j; } private void swap(int[] c , int i , int j){ int temp = c[i]; c[i] = c[j]; c[j] = temp; }
测试用例c=[3,0,6,1,5,0]。首先期望输出应该是[6,5,3,1,0,0]
但是运行结果却是[0,1,3,5,0,6]。
不仅没排对,而且在大方向上也不对,本来想从打到小排序,但是整体上看却从小到大了。
那么问题出在哪儿?
让我们一步一步分析。
首先第一次调用part方法,low=0,high=5
进入循环之后,可以知道将第1个元素0和第4个元素5交换位置,得到[3,5,6,1,0,0],此时i=1,j=4。循环继续,第一个while继续寻找比3小的数,于是它来到了元素1,此时i=3,j=4。然后第二个while开始从后往前找,找一个比3大的数,于是它来到了元素6,此时i=3,j=2。接着,按照代码的指示,程序将c[3]和c[2]交换了位置。数组现在长这样
[3,5,1,6,0,0]
然后程序发现此时i=3>j=2,所以就break了,然后按照惯例,将c[low]和c[j]交换位置,得到了
[1,5,3,6,0,0]
这不科学啊!!!!!
快排的思想是在进行一轮交换之后,在轴心左边的都比轴心大,右边的都比他小才对。这第一轮我们把3作为轴心,那前面应该是5和6才对,1是什么鬼?
仔细分析一下发现,在第一个while找到一个比3小的数,和第二个while找到一个比3大的数之后,如果立即进行交换,那么如果这是这一轮的最后一次交换,那么本来位置j上的数是比3大的,被交换到了i的位置,此时位置j上的数变得比3小,此时结束循环,需要将轴心元素换到中间来,就出现了这个bug,就是把比3小的元素换到了前面去。
所以这里应该先检查i,j的大小关系,然后在进行交换。这样来确保与轴心元素交换的数字比3大。
现在我们的part方法变成了这样:
private int part(int[] c , int low , int high){ int i = low; int j = high; while(true){ while(c[++i] >= c[low]){ if(i == high) break; } while(c[j] < c[low]){ j--; if(j == low ) break; } if( i > j) break; swap(c,i,j); } swap(c,low,j); return j; }
修改代码之后再次运行
我的天
居然报错了,ArrayIndexOutOfBoundsException。数组越界,又是哪里脚标没搞对?
可以知道最后总是会有i=j=5的时候,当判断条件i>j并不会被满足,所以还会进行下一次循环,就会出现c[6]的情况,就出现了越界。这里需要将判断条件改为i>=j。因此整个正确的代码如下:
private void quickSort(int[] c , int low , int high){ if(c.length == 0||c.length==1||low>=high) return; int mid = part(c, low, high); quickSort(c, low , mid-1); quickSort(c , mid+1, high); } private int part(int[] c , int low , int high){ int i = low; int j = high; while(true){ while(c[++i] >= c[low]){ if(i == high) break; } while(c[j] < c[low]){ j--; if(j == low ) break; } if( i >= j) break; swap(c,i,j); } swap(c,low,j); return j; } private void swap(int[] c , int i , int j){ int temp = c[i]; c[i] = c[j]; c[j] = temp; }
这次终于对了。。。。
- 关于快速排序算法
- 关于快速排序
- 关于快速排序
- 关于快速排序qsort
- 关于快速排序算法
- 关于快速排序
- 关于快速排序
- 09 关于快速排序
- 关于快速排序
- 关于快速排序
- 关于快速排序
- 关于快速排序
- 关于快速排序
- 关于快速排序 quick sort
- 关于快速排序与归并排序
- 关于快速排序,因为MixingMilk了解了快速排序
- 关于快速排序的c++算法
- 关于插入、合并、快速排序的源码
- Memcache 查看列出所有key方法
- centos6安装nginx
- Android控件架构
- 网络霸凌、收费阅读和内容创业
- DFS一直写不好啊啊啊
- 关于快速排序
- 设备World Wide Number的搜集方式
- JavaScript科普小知识
- Map获取键值
- 安卓
- 关于VB.NET中,如何得知多个radiobutton中哪个被选中(checked)
- 快播案上诉是否会对流量矿石有影响?
- shell基础用法
- AFNetworking3.0封装