快速排序
来源:互联网 发布:linux vi 移动到行尾 编辑:程序博客网 时间:2024/04/30 04:18
今天上午开始看的快速排序,原理百度出来的:
设要排序的数组是A[0]……A[N-1],首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。值得注意的是,快速排序不是一种稳定的排序算法,也就是说,多个相同的值的相对位置也许会在算法结束时产生变动。
一趟快速排序的算法是:
1)设置两个变量i、j,排序开始的时候:i=0,j=N-1;
2)以第一个数组元素作为关键数据,赋值给key,即key=A[0];
3)从j开始向前搜索,即由后开始向前搜索(j--),找到第一个小于key的值A[j],将A[j]和A[i]互换;
4)从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]和A[j]互换;
5)重复第3、4步,直到i=j; (3,4步中,没找到符合条件的值,即3中A[j]不小于key,4中A[i]不大于key的时候改变j、i的值,使得j=j-1,i=i+1,直至找到为止。找到符合条件的值,进行交换的时候i, j指针位置不变。另外,i==j这一过程一定正好是i+或j-完成的时候,此时令循环结束)。
然后自己写的第一遍排序的代码:
<pre name="code" class="java">package testjson;import org.junit.Test;public class Quicksort {private int i;private int j;int t = 0;int[] tie = new int[5];public int qp(int[] score, int i, int j) {int temp;int key;int n = j;int m = i;key = score[i];for (j = n; j > i; j--) {if (score[j] < key) {temp = score[j];score[j] = score[i];score[i] = temp;for (i = m; i < j; i++) {if (score[i] > key) {temp = score[i];score[i] = score[j];score[j] = temp;break;}}}}System.out.println("排序完成后的结果:");for (i = 0; i < score.length; i++) {System.out.print(score[i] + ",");}return j;}@Testpublic void test() {int[] score = { 3, 5, 9, 2, 1, 8, 4, 6 };i = 0;j = score.length - 1;qp(score, i, j);}}
全部排序完成需要用到递归算法,自己写的递归感觉很正确
package testjson;import org.junit.Test;public class Quicksort {private int i;private int j;int t = 0;int[] tie = new int[5];public int qp(int[] score, int i, int j) {int temp;int key;int n = j;int m = i;key = score[i];for (j = n; j > i; j--) {if (score[j] < key) {temp = score[j];score[j] = score[i];score[i] = temp;for (i = m; i < j; i++) {if (score[i] > key) {temp = score[i];score[i] = score[j];score[j] = temp;break;}}}}qp(score, j + 1, score.length - 1);qp(score, i, j - 1);System.out.println("排序完成后的结果:");for (i = 0; i < score.length; i++) {System.out.print(score[i] + ",");}return j;}@Testpublic void test() {int[] score = { 3, 5, 9, 2, 1, 8, 4, 6 };i = 0;j = score.length - 1;qp(score, i, j);}}
调试了几次逻辑走的不对,ij在第二次快排的时候最后值都不同,最后看了别人的分析才知道用到不只是递归,递归只是解决问题的方式,用的分治法,分治法的大致思想是,把问题分为小问题,用递归或者其他方式解决小问题,再把小问题合起来为问题本身
以下是别人的分析:
它的一般的算法设计模式如下:
Divide-and-Conquer(P)
1. if |P|≤n0
2. then return(ADHOC(P))
3. 将P分解为较小的子问题 P1 ,P2 ,…,Pk
4. for i←1 to k
5. do yi ← Divide-and-Conquer(Pi) △ 递归解决Pi
6. T ← MERGE(y1,y2,…,yk) △ 合并子问题
7. return(T)
其中|P|表示问题P的规模;n0为一阈值,表示当问题P的规模不超过n0时,问题已容易直接解出,不必再继续分解。ADHOC(P)是该分治法中的基本子算法,用于直接解小规模的问题P。因此,当P的规模不超过n0时直接用算法ADHOC(P)求解。算法MERGE(y1,y2,…,yk)是该分治法中的合并子算法,用于将P的子问题P1 ,P2 ,…,Pk的相应的解y1,y2,…,yk合并为P的解。
所以我的问题出在,我并没有把问题明显的细分,我只用到递归,而且递归用的不对,关键的代码是:
int middle = getMiddle(list, low, high); //将list数组进行一分为二
_quickSort(list, low, middle - 1); //对低字表进行递归排序
_quickSort(list, middle + 1, high); //对高字表进行递归排序
下边附带一下完整的代码,此代码为网上查找别人的代码改编,改日再自己写代码:
package testjson;import org.junit.Test;//网上找的实例public class Zquicksort { int a[] = {3,5,9,2,1,8,4,6}; @Test public void quickSort(){ quick(a); for(int i=0;i<a.length;i++) System.out.print(a[i]+","); } public int getMiddle(int[] list, int low, int high) { int tmp = list[low]; //数组的第一个作为中轴 while (low < high) { while (low < high && list[high] >= tmp) { high--; } list[low] = list[high]; //比中轴小的记录移到低端 while (low < high && list[low] <= tmp) { low++; } list[high] = list[low]; //比中轴大的记录移到高端 } list[low] = tmp; //中轴记录到尾 //System.out.println(tmp+","+low); System.out.println("排序完成后的结果:"+low); for(int p=0;p<a.length;p++){ System.out.print(a[p]+","); } return low; //返回中轴的位置 } public void _quickSort(int[] list, int low, int high) { if (low < high) { int middle = getMiddle(list, low, high); //将list数组进行一分为二 _quickSort(list, low, middle - 1); //对低字表进行递归排序 _quickSort(list, middle + 1, high); //对高字表进行递归排序 } } public void quick(int[] a2) { if (a2.length > 0) { //查看数组是否为空 _quickSort(a2, 0, a2.length - 1); } } }
回头看自己写的代码,我用的是FOR循环,它写的是while循环,但是我的写法是错的,正确的写法改怎么写呢。自己没看出来。。回去问了问对象,解决了,是我最后没有break所以会再次j--然后再跳出循环,这个涉及到for循环本身的执行顺序:先执行j=7代入,然后第一遍循环完成之后执行j--,然后再次判断,如果成立继续执行,不成立则跳出。我再后边语句加了break就会直接跳出for循环,不至于进行再次判断。下边是别人说的百度的:
for(a;b;c)执行顺序先执行a在判断b是否为真,若为真执行循环体,执行c然后再次判断b是否为真,若为真执行循环体执行c。。。直到b为假,跳出循环
一下是改好的代码:
package testjson;import org.junit.Test;public class Quicksort {int[] score = { 3, 5, 9, 2, 1, 8, 4, 6 };public int qp(int[] score, int i, int j) {int temp;int key;int n = j;int m = i;key = score[i];for (j = n; j > i; j--) {if (score[j] < key) {temp = score[j];score[j] = score[i];score[i] = temp;for (i = m; i < j; i++) {if (score[i] > key) {temp = score[i];score[i] = score[j];score[j] = temp;break;}}}if(i==j){break;}}System.out.println("排序完成后的结果:"+j);for (i = 0; i < score.length; i++) {System.out.print(score[i] + ",");}return j;}public void quick(int[] list, int low, int high) {if (low < high) { int middle = qp(list, low, high); //将list数组进行一分为二 quick(list, low, middle - 1); //对低字表进行递归排序 quick(list, middle + 1, high); //对高字表进行递归排序 } }@Testpublic void test() {quick(score,0,score.length-1);}}
快速排序到此技术,过两天过来改改语言表达。
本来不打算看非递归排序,感觉不怎么会用到,但是看了下别人写的代码用到栈了,这个得学啊,先留下网址,等以后看到栈的时候再看,先记录下
http://blog.csdn.net/yunzhongguwu005/article/details/9455991
http://www.douban.com/note/234724751/
1 0
- 快速排序
- 快速排序
- 快速排序
- 快速排序!
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- C/C++函数指针(typedef简化定义)
- js 把字符串当函数执行的方法
- php中'.'和'..'还有'./'和'../'都是什么意思呢?具体表示什么呢?
- 解决cannot mount volume over existing file, file exists /var/lib/docker/aufs/mnt/
- caffe 自己安装记录,cpu版
- 快速排序
- linux基本命令
- ecshop的安装与相关问题解决
- POJ 2886 Who Gets the Most Candies?
- adbo.net 使用open打开连接报错的解决办法
- asp.net学习记录
- debug下 奇葩问题
- EJB有状态的会话Bean和无状态的会话Bean的区别
- 正则表达式的简要讲解