我尝试递归地实现合并排序,不幸的是,它似乎显示O(n ^ 2)复杂度而不是期望的O(nlogn)。 这是代码,首先我调用一个驱动程序方法(在这里创建临时数组,因此它不需要为每个递归调用重新初始化):
<select [ngModel]="object">
<option *ngFor="let object of objects;let i= index;" [value]="object.value" selected="i==0">{{object.name}}</option>
</select>
一旦处理了所有驱动程序业务,就会调用mergeSortRecusive(一旦子数组达到一定大小,我就切换到插入排序。在这种情况下,INSERTTHRESHOLD设置为10):
public static <T> void mergesort(ArrayList<T> list, Comparator<? super T> comparator) {
// Create and initialize a temporary ArrayList to be passed through the
// recursive method.
ArrayList<T> temp = new ArrayList<T>();
for (int i = 0; i < list.size(); i++) {
temp.add(null);
}
mergeSortRecursive(list,temp, 0, list.size()-1, comparator);
}
最后,一旦一切都很好并且分开了,就会调用merge函数将它们全部重新组合在一起:
private static <T> void mergeSortRecursive (ArrayList<T> list, ArrayList<T> temp, int left, int right, Comparator<? super T> comparator) {
// If ArrayList size is less than the set threshold call the insertSort
// method and return results instead continuing to call the recursive method.
if(right - left < INSERTTHRESHOLD) {
insertionSort(list, left, right, comparator);
}
// Find mid point in ArrayList biased on size of array.
int mid = (left + right) / 2;
// Recursively call the mergeSortRecursive method passing the first half of the
// ArrayList.
mergeSortRecursive(list,temp, left, mid, comparator);
// Recursively call the mergeSortRecursive method passing the second half of the
// ArrayList.
mergeSortRecursive(list,temp, mid+1, right, comparator);
// Merge the two half array lists back together and return the results.
merge(list,temp, left, mid+1, right, comparator);
}
这是时间图:
这是n ^ 2的平均时间:
这里的时间超过n * log(n):
那么为什么要把这件事拿这么久?
答案 0 :(得分:0)
您可以在系统上测试此示例代码吗?它是一个优化的自顶向下合并排序,它在int(primitive)上运行。这个例子在大约1.2秒内排序10,000,000个整数。对于你的例子,我想知道所有这些set调用的开销(做这些释放并分配内存?),以及arraylist(指向对象的指针数组)的开销。
package jsorttd;
import java.util.Random;
public class jsorttd {
static void MergeSort(int[] a) // entry function
{
if(a.length < 2) // if size < 2 return
return;
int[] b = new int[a.length];
MergeSortAtoA(a, b, 0, a.length);
}
static void MergeSortAtoA(int[] a, int[] b, int ll, int ee)
{
if(ee - ll > 1) {
int rr = (ll + ee)>>1; // midpoint, start of right half
MergeSortAtoB(a, b, ll, rr);
MergeSortAtoB(a, b, rr, ee);
Merge(b, a, ll, rr, ee); // merge b to a
}
}
static void MergeSortAtoB(int[] a, int[] b, int ll, int ee)
{
if(ee - ll > 1) {
int rr = (ll + ee)>>1; // midpoint, start of right half
MergeSortAtoA(a, b, ll, rr);
MergeSortAtoA(a, b, rr, ee);
Merge(a, b, ll, rr, ee); // merge a to b
} else if((ee - ll) == 1) { // if just one element
b[ll] = a[ll]; // copy a to b
}
}
static void Merge(int[] a, int[] b, int ll, int rr, int ee) {
int o = ll; // b[] index
int l = ll; // a[] left index
int r = rr; // a[] right index
while(true){ // merge data
if(a[l] <= a[r]){ // if a[l] <= a[r]
b[o++] = a[l++]; // copy a[l]
if(l < rr) // if not end of left run
continue; // continue (back to while)
do // else copy rest of right run
b[o++] = a[r++];
while(r < ee);
break; // and return
} else { // else a[l] > a[r]
b[o++] = a[r++]; // copy a[r]
if(r < ee) // if not end of right run
continue; // continue (back to while)
do // else copy rest of left run
b[o++] = a[l++];
while(l < rr);
break; // and return
}
}
}
public static void main(String[] args) {
int[] a = new int[10000000];
Random r = new Random();
for(int i = 0; i < a.length; i++)
a[i] = r.nextInt();
long bgn, end;
bgn = System.currentTimeMillis();
MergeSort(a);
end = System.currentTimeMillis();
for(int i = 1; i < a.length; i++){
if(a[i-1] > a[i]){
System.out.println("failed");
break;
}
}
System.out.println("milliseconds " + (end-bgn));
}
}