我无法弄清楚为什么我使用ArrayLists的合并排序程序的算法不起作用......如果伙计们和gals可以帮助我弄明白这将是惊人的!!打印所需的格式需要每隔20个数字标记每个数字并放在新行上。我的程序也仅限于标准的Java包。可以找到示例输入和输出here。这是我的代码:
import java.io.*;
import java.util.*;
public class MergeSort {
public static void main(String[] args) throws IOException{
Scanner in = new Scanner(System.in);
Random r = new Random();
int size, largestInt, holder;
System.out.println("How many integers would you like me to create?");
size = in.nextInt();
ArrayList<Integer>list = new ArrayList<Integer>(size);
System.out.println("What would the largest integer be?");
largestInt = in.nextInt();
for(int i = 0; i < size; i++){
holder = r.nextInt(largestInt + 1);
list.add(holder);
}
mergeSort(list);
for (int j = 0; j < list.size(); j++) {
if(j == 19 || j == 39 || j == 59 || j == 79 || j == 99 || j == 119 || j == 139 || j == 159 || j == 179 || j == 199){
System.out.print(list.get(j));
System.out.println();
}
else{
System.out.print(list.get(j) + "\t");
}
}
}
static void mergeSort(ArrayList<Integer> list) {
if (list.size() > 1) {
int q = list.size()/2;
ArrayList<Integer> leftList = new ArrayList<Integer>();
for(int i = 0; i >0 && i <= q; i++){
leftList.add(list.get(i));
}
ArrayList<Integer> rightList = new ArrayList<Integer>();
for(int j = 0; j > q && j < list.size(); j++){
rightList.add(list.get(j));
}
mergeSort(leftList);
mergeSort(rightList);
merge(list,leftList,rightList);
}
}
static void merge(ArrayList<Integer> a, ArrayList<Integer> l, ArrayList<Integer> r) {
int totElem = l.size() + r.size();
int i,li,ri;
i = li = ri = 0;
while ( i < totElem) {
if ((li < l.size()) && (ri<r.size())) {
if (l.get(li) < r.get(ri)) {
a.set(i, l.get(li));
i++;
li++;
}
else {
a.set(i, r.get(ri));
i++;
ri++;
}
}
else {
if (li >= l.size()) {
while (ri < r.size()) {
a.set(i, r.get(ri));
i++;
ri++;
}
}
if (ri >= r.size()) {
while (li < l.size()) {
a.set(i, l.get(li));
li++;
i++;
}
}
}
}
}
提前致谢!
答案 0 :(得分:0)
您的问题尚不清楚,但由于您需要实施合并排序算法,我认为这是为您打破的部分。一旦你有一个正确排序的列表,格式打印应该通过试验和错误相当容易。
我认为您的解决方案中的问题非常复杂。 MergeSort是最简单的排序算法之一,但你的代码远非简单。
考虑Merge Sort如何工作 - 它本质上是递归的,因为它是一种分而治之的方法。它通过将其分解为小的简单问题来解决一个大的复杂问题,并且基本上只是合并来自所有这些问题的结果 - 您的MergeSort算法只需要包含它。
如果我们写完,您需要执行以下步骤:
(1)检查列表是否只包含一个元素 - 然后它已经排序
(2)将输入拆分为大小相等的列表,并在继续(递归步骤)之前对其进行排序
(3)合并两个已排序的列表,并返回单个排序列表。
我看到你有一个复杂的合并方法,并使用基本的迭代来分割部分。 Java List(例如ArrayList
的超类)提供.subList(fromIndex, toIndex)
将列表拆分为较小的列表。你应该用它。对于合并部分:
基于维基百科的这个动画
如何考虑合并两个列表应该相当简单:
首先将两个列表都维护为易于从中删除对象的列表。由于此时我们知道列表将被排序,我们只对每个列表中的第一个对象(最小元素)感兴趣。
其次,我们只需要比较每个列表的第一个元素,从其各自的列表中删除最小的两个元素,并将其添加到我们的排序列表中。我们一直这样做,直到两个列表都是空的 - 此时我们合并了我们的列表。
在Java中,这表明我们应该使用合并部分的数据结构,它允许我们查看每个列表的第一个元素,并快速删除我们感兴趣的那个。在Java中,这个数据结构是LinkedList - ArrayList在这项任务中执行非常糟糕,并没有提供适当的方法来执行此操作。 LinkedList表现为队列,并提供方便在列表末尾检查和删除对象的方法,例如第一个元素。
因此,您应该重新考虑您的实施策略,并根据您应该如何攻击MergeSort算法来简化代码。如果看起来有点令人兴奋,那么只使用标准API(没有构建排序方法)的Java中的MergeSort示例实现。
希望它有所帮助。
import java.util.LinkedList;
import java.util.Random;
import java.util.List;
public class Main {
public static void main(String[] args){
Random random = new Random();
LinkedList<Integer> unsorted = new LinkedList<Integer>();
for(int i = 0; i<100; i++){
unsorted.add(random.nextInt(100));
}
System.out.println("unsorted: " + unsorted.toString());
List<Integer> sorted = mergeSort(unsorted);
System.out.println("sorted: " + sorted.toString());
}
//Recursive function for sorting a LinkedList
private static LinkedList<Integer> mergeSort(LinkedList<Integer> unsorted){
//If the list only contains 1 object it is sorted
if(unsorted.size() == 1){
return unsorted;
}
//Split the list in two parts and create a new list to store our sorted list
LinkedList<Integer> left = mergeSort(new LinkedList<Integer>(unsorted.subList(0, unsorted.size()/2)));
LinkedList<Integer> right = mergeSort(new LinkedList<Integer>(unsorted.subList(unsorted.size()/2, unsorted.size())));
LinkedList<Integer> sorted = new LinkedList<Integer>();
//Actual loop for merging the two sublists. Using LinkedLists, this is efficient. (Compared to ArrayList)
while(!left.isEmpty() || !right.isEmpty()){
Integer leftInt = left.peekFirst();
Integer rightInt = right.peekFirst();
if(!(leftInt == null) && !(rightInt == null)){
if(leftInt < rightInt){
sorted.add(left.pollFirst());
}
else{
sorted.add(right.pollFirst());
}
}
else if(leftInt == null){
sorted.add(right.pollFirst());
}
else{
sorted.add(left.pollFirst());
}
}
return sorted;
}
}