[英]How can I implement mergesort for a ArrayList?
I have a java code of mergesort for ArrayList
but it doesn't sort correctly the ArrayList
.我有一个 ArrayList 的ArrayList
排序代码,但它没有正确排序ArrayList
。 But I don't find the mistake.但我没有发现错误。
The code is:代码是:
public void mergeSort(ArrayList<Integer> list, int beg, int fin) {
if (beg < fin) {
int mid= (beg + fin) / 2;
mergeSort(list, beg, mid);
mergeSort(list, mid + 1, fin);
Merge(list, beg, mid, fin);
}
}
public void Merge(ArrayList<Integer> list, int beg, int mid, int fin) {
ArrayList<Integer> left = new ArrayList<>(list.subList(beg, mid));
ArrayList<Integer> right = new ArrayList<>(list.subList(mid, fin));
int i = 0;
int j = 0;
int k = beg;
while (i < left.size() && j < right.size()) {
if (left.get(i) <= right.get(i)) {
list.set(k, left.get(i));
i++;
} else {
list.set(k, right.get(j));
j++;
}
k++;
}
while (i < left.size()) {
list.set(k, left.get(i));
i++;
k++;
}
while (j < right.size()) {
try {
list.set(k, right.get(j));
j++;
k++;
}
}
}
When I call it from other class...当我从其他 class 调用它时......
jpanel4.mergeSort(jpanel4.lista, 0, jpanel4.lista.size() - 1);
(Merge is in jpanel4 class). (合并在 jpanel4 类中)。
I converted a mergesort code for arrays to that, because it will work fine with other code that I have.我将 arrays 的合并排序代码转换为该代码,因为它可以与我拥有的其他代码一起正常工作。
Thanks.谢谢。
Let's use half-closed interval [beg, fin)
because this approach is used in the most of in-build methods of Java, C++, etc.让我们使用半闭区间[beg, fin)
因为这种方法用于 Java、C++ 等的大多数内置方法中。
Then call should be:那么调用应该是:
jpanel4.mergeSort(jpanel4.lista, 0, jpanel4.lista.size());
// ^ no -1
Now let's see how you divide given interval.现在让我们看看如何划分给定的区间。 Let's use [beg, mid)
and [mid, end)
intervals.让我们使用[beg, mid)
和[mid, end)
间隔。 If l >= r
, then interval is empty.如果l >= r
,则区间为空。
But if given interval has length 1, it's going to be divided into two intervals of length 0 and 1 and mergeSort
will be recursively called to sort the exact same interval.但是如果给定区间的长度为 1,它将被分成长度为 0 和 1 的两个区间,并且将递归调用mergeSort
以对完全相同的区间进行排序。 You don't need to sort one-element array, it's already sorted.您不需要对单元素数组进行排序,它已经排序。
So mergeSort
should look like:所以mergeSort
应该是这样的:
public void mergeSort(ArrayList<Integer> list, int beg, int fin){
if(beg + 1 < fin){
// ^^^ added +1 to ensure we sort only intervals with length >= 2
int mid = (beg+fin)/2;
mergeSort(list, beg, mid);
mergeSort(list, mid, fin);
// ^ no +1
Merge(list, beg, mid, fin);
}
}
Also there's a mistake in Merge
:在Merge
中也有一个错误:
public void Merge(ArrayList<Integer> list, int beg, int mid, int fin){
// ...
while (i < left.size() && j < right.size()) {
if (left.get(i) <= right.get(j)) {
// ^ you should compare left[i] and right[j]
list.set(k, left.get(i));
i++;
} else {
list.set(k, right.get(j));
j++;
}
k++;
}
// ...
}
Check my version of merge sort using array list hope it help you : https://github.com/murari99732/solutionleetcode-adventofcode/blob/master/PracticeAlgo/src/LeetCode/MergeSort.java
public static void mergeSort(List<Integer> arr, int start, int end) {
if (start != end) {
int mid = (start + end) / 2;
mergeSort(arr, start, mid);
mergeSort(arr, mid + 1, end);
merge(arr, start, mid, end);
}
}
private static void merge(List<Integer> arr, int start, int mid, int end) {
int i = start;
int j = mid + 1;
int k = 0;
int[] temp = new int[end - start + 1];
while ((i <= mid) && (j <= end)) {
if (arr.get(i) < arr.get(j))
temp[k++] = arr.get(i++);
else
temp[k++] = arr.get(j++);
}
while (i <= mid) {
temp[k++] = arr.get(i++);
}
while (j <= end) {
temp[k++] = arr.get(j++);
}
for (i = start; i <= end; i++) {
arr.remove(i);
int e = temp[i - start];
arr.add(i, e);
}
}
The main bug is a simple typo: if (left.get(i) <= right.get(i)) {
should be:主要错误是一个简单的错字: if (left.get(i) <= right.get(i)) {
应该是:
if (left.get(i) <= right.get(j)) {
You also have a problem with the array index values and boundaries: the beg
and mid
indices should be included and the fin
(end?) should be excluded.数组索引值和边界也有问题:应该包括beg
和mid
索引,并且应该排除fin
(结束?)。 This also removes the need for +1
/ -1
adjustments.这也消除了+1
/ -1
调整的需要。
There is a more subtile bug in int mid = (beg + fin) / 2;
int mid = (beg + fin) / 2;
有一个更微妙的错误。 : computing this sum may overflow for very large arrays. :对于非常大的 arrays,计算此总和可能会溢出。 It is better to write:最好写:
int mid = beg + (fin - beg) / 2;
Once you correct these issues, you can remove the try
block.更正这些问题后,您可以删除try
块。
Here is a modified version:这是修改后的版本:
public void mergeSort(ArrayList<Integer> list, int beg, int fin) {
if (fin - beg >= 2) {
int mid = beg + (fin - beg) / 2;
mergeSort(list, beg, mid);
mergeSort(list, mid, fin);
Merge(list, beg, mid, fin);
}
}
public void Merge(ArrayList<Integer> list, int beg, int mid, int fin) {
ArrayList<Integer> left = new ArrayList<Integer>(list.subList(beg, mid));
ArrayList<Integer> right = new ArrayList<Integer>(list.subList(mid, fin));
int i = 0;
int j = 0;
int k = beg;
while (i < left.size() && j < right.size()) {
if (left.get(i) <= right.get(j)) {
list.set(k, left.get(i++));
} else {
list.set(k, right.get(j++));
}
k++;
}
while (i < left.size()) {
list.set(k, left.get(i++));
k++;
}
while (j < right.size()) {
list.set(k, right.get(j++));
k++;
}
}
You would call this method with jpanel4.mergeSort(jpanel4.lista, 0, jpanel4.lista.size());
您可以使用jpanel4.mergeSort(jpanel4.lista, 0, jpanel4.lista.size());
调用此方法
Note that Merge
can be simplified as the last loop is redundant, the remaining elements from right
are already at the end of list
.请注意, Merge
可以简化,因为最后一个循环是多余的, right
的剩余元素已经在list
的末尾。 As a matter of fact, there is no need to save the elements from the right part as they are always copied to lower or equal index values.事实上,没有必要保存右边部分的元素,因为它们总是被复制到较低或相等的索引值。
Here is a simplified version:这是一个简化版本:
public void Merge(ArrayList<Integer> list, int beg, int mid, int fin) {
ArrayList<Integer> left = new ArrayList<Integer>(list.subList(beg, mid));
for (int i = 0, j = mid, k = beg; i < left.size(); k++) {
if (j >= fin || left.get(i) <= list.get(j)) {
list.set(k, left.get(i++));
} else {
list.set(k, list.get(j++));
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.