黑马程序员技术交流社区
标题:
有关快速排序的问题
[打印本页]
作者:
十字路口
时间:
2013-6-1 00:32
标题:
有关快速排序的问题
本帖最后由 十字路口 于 2013-6-1 10:13 编辑
public class Quicksort{
public static int partion(int values[],int left,int right){
int i=left;
int j=right;
int temp;
int key=values[left];
while(i<j){
while(values
<=key){
i++;
}
while(values[j]>=key){
j--;
}
if(i<=j){
temp=values
;
values
=values[j];
values[j]=temp;
i++;
j--;
}
}
return i;
}
public static void qsort(int values[],int left,int right){
int temp=0;
if(left<right){
temp=partion(values, left, right);
qsort(values, left, temp-1);
qsort(values, temp+1, right);
}
}
public static void main(String[] args) {
int a[]={34,43,6,12,78,37,92,14};
qsort(a, 0, a.length-1);
for(int i=0;i<a.length;i++){
System.out.print(a
+" ");
}
}
}
为什么这是个死循环。。。 while(values
<=key){
i++;
}
while(values[j]>=key){
j--;
}
把段代码改成
while(values
<key){
i++;
}
while(values[j]>key){
j--;
}
结果又不正确为什么呢?
作者:
神之梦
时间:
2013-6-1 01:58
首先这里while(values
<=key)可以写等于,但是还缺少一个判断,就是i<j,因为如果不加这个判断,角标肯定会出界,所以运行时会出现错误。
这里可以写成while(i<j&&values
<=key)
还有 if(i<=j){
temp=values
;
values
=values[j];
values[j]=temp;
i++;
j--;
}
这里不能这么写,比如只有三个数,你去代入下就知道肯定会排出错误结果了
我之前写的一段代码,你可以看一下:
/*
需求:使用快速排序的方法对数组进行升序排列
思路:1、快速排序是先利用数组的一个元素为参照,也叫枢轴。从左右两边分别与其比较,这是可以定义角标变量,左角标变量向右移,右的向左右,知道左大于等于右时,完成第一轮排序比较。
第一轮比较后将大于这个元素的数放到右边,小于这个元素的数放到左边
2、再对左右两边根据第一步的思想进行排序。如:把左边的的部分当作一个数组,再从中选一个元素做参照。以此反复。
*/
class QuickSort
{
public static void quickSort(int[] arr ,int left,int right)
{
int l=left,r=right,pivot=arr[l];//pivot定义枢轴
while(l<r)//判断一轮是否进行完了
{
while(l<r && arr[r]>=pivot)//判断右边的数是否都大于pivot
r--;
//如果小于pivot,就将小于的元素放到左边去
if(l<r)
{
arr[l]=arr[r];
l++;//l++是为了避免重复判断
}
while(l<r && arr[l]<=pivot)//判断左边的数是否都小于pivot
l++;
//如果大于privot,就将大于的元素放到右边去
if(l<r)
{
arr[r]=arr[l];
r--;
}
}
arr[l]=pivot;//将作为参照的元素放到分割位置
//当一轮比较完,l!=left,说明左边还有大于1个元素,那么继续排序
if(l>left)
{
quickSort(arr,left,l-1);
}
//当一轮比较完,r!=right,说明右边边还有大于1个元素,那么继续排序
if(r<right)
{
quickSort(arr,l+1,right);
}
}
//遍历数组
public static void printArray(int[] arr)
{
System.out.print("[");
for(int x=0;x<arr.length-1;x++)
System.out.print(arr[x]+",");
System.out.println(arr[arr.length-1]+"]");
}
}
class Test
{
public static void main(String[] args)
{
int[] arr1={1,2};
int[] arr2={34,43,6,12,78,37,92,14};
int[] arr3={2,2,2,10,2,3,3,3,3,2,2,2};
QuickSort.printArray(arr1);
QuickSort.quickSort(arr1,0,arr1.length-1);
QuickSort.printArray(arr1);
QuickSort.printArray(arr2);
QuickSort.quickSort(arr2,0,arr2.length-1);
QuickSort.printArray(arr2);
QuickSort.printArray(arr3);
QuickSort.quickSort(arr3,0,arr3.length-1);
QuickSort.printArray(arr3);
}
}
复制代码
作者:
liujkh123
时间:
2013-6-1 08:55
首先,楼主的代码从头到尾没有对第一个数组元素的操作,仔细分析一下34的位置永远在首位
我跟着程序的思路理了一个程序运行流程给楼主,至于这个问题怎么解决,代码重构了
首先:34,43,6,12,78,37,92,14
第一次排序 i =1, j = 6;交换i,j的位置得到34,92,6,12,78,37,43,14,;i++后i=2,j--后j=5,返回2
第二次排序为前一截(values, 0, 1)就是给34,92排序,这里面不会执行交换,但是因为34<92,i会自加两下,所以最后返回的是i=2;
然后就无限重复第二步、、
这个问题出现的关键在于楼主代码没有对用作标杆的元素换位置,快速排序的核心思路就是在每一轮排序后,标杆元素在中间,左边全比它小,右边全比它大。然后再对左右分别进行排序。
下面是一个比较简洁的快速排序代码,希望能帮到你
/**
* 交换指定数组a的两个变量的值
* @param a 数组应用
* @param i 数组下标
* @param j 数组下标
*/
public void swap(int a[], int i, int j) {
if(i == j) return;
int tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
/**
*
* @param array 待排序数组
* @param low 数组下标下界
* @param high 数组下标上界
* @return pivot
*/
public int partition(int array[], int low, int high) {
//当前位置为第一个元素所在位置
int p_pos = low;
//采用第一个元素为轴
int pivot = array[p_pos];
for (int i = low + 1; i <= high; i++) {
if (array[i] < pivot) {
p_pos++;
swap(array, p_pos, i);
}
}
swap(array, low, p_pos);
return p_pos;
}
/**
* 快速排序实现
* @param array
* @param low
* @param high
*/
public void quickSort(int array[], int low, int high) {
if (low < high) {
int pivot = partition(array, low, high);
quickSort(array, low, pivot - 1);
quickSort(array, pivot + 1, high);
}
}
复制代码
作者:
十字路口
时间:
2013-6-1 09:27
灰常感谢各位大虾们,看了你们的提示,学到了很多。问题解决了。。。。。。
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2