Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用java实现的中值为quickselect选择pivot?_Java_Algorithm_Median_Median Of Medians_Quickselect - Fatal编程技术网

使用java实现的中值为quickselect选择pivot?

使用java实现的中值为quickselect选择pivot?,java,algorithm,median,median-of-medians,quickselect,Java,Algorithm,Median,Median Of Medians,Quickselect,我在github中找到了这段代码,用于quickselect算法,也称为order statistics。这段代码运行良好 我不理解medianOf3方法,它应该按排序顺序排列第一个、中间和最后一个索引。但实际上,在调用medianof3方法后,当我输出数组时,它不会。 除了最后一次调用swap(list,centerIndex,rightIndex-1)之外,我可以按照这个方法进行操作。有人能解释为什么叫这个吗 import java.util.Arrays; /** * This pr

我在github中找到了这段代码,用于
quickselect
算法,也称为
order statistics
。这段代码运行良好

我不理解
medianOf3
方法,它应该按排序顺序排列第一个、中间和最后一个索引。但实际上,在调用
medianof3
方法后,当我输出数组时,它不会。 除了最后一次调用
swap(list,centerIndex,rightIndex-1)之外,我可以按照这个方法进行操作。有人能解释为什么叫这个吗

import java.util.Arrays;



/**
* This program determines the kth order statistic (the kth smallest number in a
* list) in O(n) time in the average case and O(n^2) time in the worst case. It
* achieves this through the Quickselect algorithm.
*
* @author John Kurlak <john@kurlak.com>
* @date 1/17/2013
*/
public class Quickselect {
   /**
* Runs the program with an example list.
*
* @param args The command-line arguments.
*/
   public static void main(String[] args) {
       int[] list = { 3, 5, 9, 10, 7, 40, 23, 45, 21, 2 };
       int k = 6;
       int median = medianOf3(list, 0, list.length-1);
       System.out.println(median);
       System.out.println("list is "+ Arrays.toString(list));
       Integer kthSmallest = quickselect(list, k);

       if (kthSmallest != null) {
           System.out.println("The kth smallest element in the list where k=" + k + " is " + kthSmallest + ".");
       } else {
           System.out.println("There is no kth smallest element in the list where k=" + k + ".");
       }
       System.out.println(Arrays.toString(list));
   }

   /**
* Determines the kth order statistic for the given list.
*
* @param list The list.
* @param k The k value to use.
* @return The kth order statistic for the list.
*/
   public static Integer quickselect(int[] list, int k) {
       return quickselect(list, 0, list.length - 1, k);
   }

   /**
* Recursively determines the kth order statistic for the given list.
*
* @param list The list.
* @param leftIndex The left index of the current sublist.
* @param rightIndex The right index of the current sublist.
* @param k The k value to use.
* @return The kth order statistic for the list.
*/
   public static Integer quickselect(int[] list, int leftIndex, int rightIndex, int k) {
       // Edge case
       if (k < 1 || k > list.length) {
           return null;
       }

       // Base case
       if (leftIndex == rightIndex) {
           return list[leftIndex];
       }

       // Partition the sublist into two halves
       int pivotIndex = randomPartition(list, leftIndex, rightIndex);
       int sizeLeft = pivotIndex - leftIndex + 1;

       // Perform comparisons and recurse in binary search / quicksort fashion
       if (sizeLeft == k) {
           return list[pivotIndex];
       } else if (sizeLeft > k) {
           return quickselect(list, leftIndex, pivotIndex - 1, k);
       } else {
           return quickselect(list, pivotIndex + 1, rightIndex, k - sizeLeft);
       }
   }

   /**
* Randomly partitions a set about a pivot such that the values to the left
* of the pivot are less than or equal to the pivot and the values to the
* right of the pivot are greater than the pivot.
*
* @param list The list.
* @param leftIndex The left index of the current sublist.
* @param rightIndex The right index of the current sublist.
* @return The index of the pivot.
*/
   public static int randomPartition(int[] list, int leftIndex, int rightIndex) {
       int pivotIndex = medianOf3(list, leftIndex, rightIndex);
       int pivotValue = list[pivotIndex];
       int storeIndex = leftIndex;

       swap(list, pivotIndex, rightIndex);

       for (int i = leftIndex; i < rightIndex; i++) {
           if (list[i] <= pivotValue) {
               swap(list, storeIndex, i);
               storeIndex++;
           }
       }

       swap(list, rightIndex, storeIndex);

       return storeIndex;
   }

   /**
* Computes the median of the first value, middle value, and last value
* of a list. Also rearranges the first, middle, and last values of the
* list to be in sorted order.
*
* @param list The list.
* @param leftIndex The left index of the current sublist.
* @param rightIndex The right index of the current sublist.
* @return The index of the median value.
*/
   public static int medianOf3(int[] list, int leftIndex, int rightIndex) {
       int centerIndex = (leftIndex + rightIndex) / 2;

       if (list[leftIndex] > list[rightIndex]) {
           swap(list, leftIndex, centerIndex);
       }

       if (list[leftIndex] > list[rightIndex]) {
           swap(list, leftIndex, rightIndex);
       }

       if (list[centerIndex] > list[rightIndex]) {
           swap(list, centerIndex, rightIndex);
       }

       swap(list, centerIndex, rightIndex - 1);

       return rightIndex - 1;
   }

   /**
* Swaps two elements in a list.
*
* @param list The list.
* @param index1 The index of the first element to swap.
* @param index2 The index of the second element to swap.
*/
   public static void swap(int[] list, int index1, int index2) {
       int temp = list[index1];
       list[index1] = list[index2];
       list[index2] = temp;
   }
}
导入java.util.array;
/**
*此程序确定第k个顺序统计(一个序列中的第k个最小数字)
*列出平均情况下的O(n)时间和最坏情况下的O(n^2)时间。信息技术
*通过Quickselect算法实现这一点。
*
*@作者约翰·库尔拉克
*@date 1/17/2013
*/
公共类Quickselect{
/**
*使用示例列表运行程序。
*
*@param指定命令行参数。
*/
公共静态void main(字符串[]args){
int[]list={3,5,9,10,7,40,23,45,21,2};
int k=6;
整数中位数=medianOf3(list,0,list.length-1);
系统输出打印LN(中值);
System.out.println(“list is”+Arrays.toString(list));
整数kthSmallest=quickselect(列表,k);
如果(kthSmallest!=null){
System.out.println(“列表中的第k个最小元素,其中k=“+k+”是“+kthSmallest+”);
}否则{
System.out.println(“列表中没有第k个最小元素,其中k=“+k+”);
}
System.out.println(Arrays.toString(list));
}
/**
*确定给定列表的第k个顺序统计信息。
*
*@param列出列表。
*@param k要使用的k值。
*@返回列表的第k个顺序统计信息。
*/
公共静态整数quickselect(int[]列表,int k){
返回quickselect(list,0,list.length-1,k);
}
/**
*递归地确定给定列表的第k个顺序统计信息。
*
*@param列出列表。
*@param leftIndex当前子列表的左索引。
*@param rightIndex当前子列表的右索引。
*@param k要使用的k值。
*@返回列表的第k个顺序统计信息。
*/
公共静态整数quickselect(int[]列表、int leftIndex、int rightIndex、int k){
//边缘案例
if(k<1 | | k>list.length){
返回null;
}
//基本情况
如果(leftIndex==rightIndex){
返回列表[leftIndex];
}
//将子列表分成两半
int pivotIndex=randomPartition(列表、左索引、右索引);
int sizeLeft=pivotIndex-leftIndex+1;
//以二进制搜索/快速排序方式执行比较和递归
如果(sizeLeft==k){
返回列表[数据透视索引];
}else if(sizeLeft>k){
返回quickselect(列表、左索引、数据透视索引-1、k);
}否则{
返回quickselect(列表,数据透视索引+1,右索引,k-sizeLeft);
}
}
/**
*围绕轴随机划分一个集合,使值向左移动
*轴的值小于或等于轴和轴的值
*轴的右侧大于轴的右侧。
*
*@param列出列表。
*@param leftIndex当前子列表的左索引。
*@param rightIndex当前子列表的右索引。
*@返回轴的索引。
*/
公共静态int-randomPartition(int[]列表、int-leftIndex、int-righIndex){
int pivotIndex=medianOf3(列表、左索引、右索引);
int pivotValue=列表[数据透视索引];
int storeIndex=leftIndex;
交换(列表、数据透视索引、右索引);
for(int i=左索引;i<右索引;i++){
if(列表[i]列表[rightIndex]){
交换(列表、左索引、中心索引);
}
如果(列表[leftIndex]>列表[rightIndex]){
交换(列表、左索引、右索引);
}
if(列表[centerIndex]>列表[rightIndex]){
交换(列表、中心索引、右索引);
}
交换(列表、中心索引、右索引-1);
返回右索引-1;
}
/**
*交换列表中的两个元素。
*
*@param列出列表。
*@param index1要交换的第一个元素的索引。
*@param index2要交换的第二个元素的索引。
*/
公共静态无效交换(int[]列表,int index1,int index2){
int temp=列表[index1];
列表[index1]=列表[index2];
列表[index2]=温度;
}
}

函数
medianOf3
用于定义左中位数和右中位数的顺序。最后一条语句

swap(列表、中心索引、右索引-1)

用于实现排序的以下先决条件:

但是,, quickselect不是像在快速排序中那样递归到两边,而是 只会递归到一个面–元素所在的面 搜索。这降低了O(n logn)(in)的平均复杂度 快速排序)到O(n)(在快速选择中)

然后算法继续进行:

   for (int i = leftIndex; i < rightIndex; i++) {
       if (list[i] <= pivotValue) {
           swap(list, storeIndex, i);
           storeIndex++;
       }
   }
for(int i=leftIndex;iif(list[i]因此我编写了原始代码,但在使其可读性方面做得很差

回过头来看,我不认为这行代码是必要的,但我认为这是一个小优化。如果我们删除这行代码并返回
centerIndex
,它似乎可以正常工作

不幸的是,它执行的优化应该从
medianOf3()
中重构出来,并移到
randomPartition()

本质上,优化是我们希望在分区之前尽可能地“部分排序”子阵列。原因是:我们的数据排序越多,我们未来的分区选择就越好,这意味着我们的运行时间有望更接近O(n)而不是O(n^2)
method,我们将轴值移动到子数组的最右侧