#java #insert #arraylist #mergesort #insertion-sort
#java #вставить #arraylist #сортировка слиянием #вставка-сортировка
Вопрос:
У меня возникли некоторые проблемы, пытаясь выяснить, как вставить целое число с помощью сканера в ArrayList. Я не настолько хорош (на самом деле даже не очень хорош) в Java, но я просто пытаюсь разобраться в некоторых вещах, и любая помощь была бы отличной.
package mySort;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Scanner;
public class MergeInsert {
private int limit = 100;
//private int size = 0;
private ArrayList<Integer> ArrayToSort;
public MergeInsert(int x) {
ArrayToSort = new ArrayList<Integer>(x);
}
public MergeInsert(Scanner integerScan){
int j = 0;
while(integerScan.hasNextInt()){
this.insert(integerScan.hasNextInt());
if (j % 10000 == 0){
long time = System.nanoTime();
System.out.println(j "," time);
}
}
}
public void insert(int x){
for(int i=0; i<ArrayToSort.size(); i ){
ArrayToSort(size ) = x;
}
}
// public MergeInsert(int v){
// int val = v;
// }
// public void insertFile(){
// try {
// Scanner integerScan = new Scanner(new FileInputStream(""));
// while(integerScan.hasNextInt()){
// new MergeInsert(integerScan.nextInt());
// }
// }
// catch (FileNotFoundException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
// }
public void sort(){
}
public void mergeSort(ArrayList<Integer> in, int low,int high){
int n = in.size();
int mid = (high low)/2;
if (n<2){ //already sorted
return;
}
if ((high - low) < limit){
insertionSort(in);
}
ArrayList<Integer> in1 = new ArrayList<Integer>(); //helper
ArrayList<Integer> in2 = new ArrayList<Integer>(); //helper
int i=0;
while (i < n/2){ //moves the first half to the helper
in1.add(in.remove(0));
i ;
}
while (!in.isEmpty()) //moves the second half to the helper
in2.add(in.remove(0));
mergeSort(in1, low, mid); //breaks it down some more like mergesort should
mergeSort(in2, mid 1, high); //does it again
merge(in1,in2,in); //trying to build it up again
}
public void merge(ArrayList<Integer> in, ArrayList<Integer> in1, ArrayList<Integer> in2){
while (!in1.isEmpty() || !in2.isEmpty()) //as long as both helpers still have elements
if ((in1.get(0).compareTo(in2.get(0)) <= 0)) //comparison to rebuild
in.add(in1.remove(0)); //building it back up
else
in.add(in2.remove(0)); //still building
while(!in1.isEmpty()) //as long as the first helper isn't empty keep building
in.add(in1.remove(0));
while(!in2.isEmpty()) //as long as the second helper isn't empty keep building
in.add(in2.remove(0));
}
public ArrayList<Integer> insertionSort(ArrayList<Integer> in){
int index = 1;
while (index<in.size()){
insertSorted((int)(in.get(index)),in,index);
index = index 1;
}
return in;
}
public ArrayList<Integer> insertSorted(Integer s, ArrayList<Integer> in, int index){
int loc = index-1;
while((loc>=0) || s.compareTo(in.get(loc)) <= 0){
in.set(loc 1, in.get(loc));
loc = loc -1;
}
in.set(loc 1, s);
return in;
}
/**
* @param args
* @throws FileNotFoundException
*/
public static void main(String[] args) throws FileNotFoundException {
Scanner integerScan = new Scanner(new FileInputStream("src/myRandomNumbers.txt"));
MergeInsert myObject = new MergeInsert(integerScan);
myObject.sort();
}
}
Это не полностью закончено, но идея, стоящая за всем этим, состоит в том, чтобы попытаться улучшить сортировку слиянием. В основном, как только элементы разбиваются до определенной точки, обрезается до InsertionSort, потому что это обычно лучше для действительно маленьких (действительно маленьких относительных) наборов данных.
Комментарии:
1. В качестве примечания, ваш порог для перехода к сортировке вставкой вместо сортировки слиянием ДЕЙСТВИТЕЛЬНО высок. В JDK это 7. У вас это 100. :-O
2. На данный момент я просто использовал его в качестве заполнителя. Я собирался запустить его в списках разного размера, чтобы посмотреть, что будет лучше для наборов разного размера.
3. Профилирование и настройка констант — лучший способ сделать это! 🙂
Ответ №1:
public void insert(int x){
ArrayToSort.add(x); // add it to the end
}
Причина в том … даже если вы перейдете
ArrayToSort = new ArrayList<Integer>(100000);
Он по-прежнему имеет размер 0. Он просто имеет ЕМКОСТЬ 100000.
Комментарии:
1. Извините, я забыл, что добавил туда ссылку на размер. Я просто пытался посмотреть, помогло ли это перед публикацией, очевидно, нет.
2. Если вы не указываете размер, он просто делает
new ArrayList<Integer>(10)
это вместо этого. Вы можете переопределить значение по умолчанию 10, если хотите.3. Разве ArrayLists не расширяются по мере необходимости во время выполнения? Например, если я читаю 1000 элементов, он будет расширяться, чтобы удерживать их, и если я прочитаю из другого файла с 1 миллионом, он также должен обработать это без каких-либо изменений в коде. Или я неправильно понимаю?
4. Ваше понимание правильное. Но, если вы ЗНАЕТЕ, что будете получать по крайней мере определенное количество записей, почему бы не сэкономить пару расширений, которые вам не нужны? По умолчанию это 10, поэтому он будет расширяться при 20, 40, 80, 160, 320, 640, 1280, 2560, 5120, 10240, 20480, 40960, 81920, 163840, 327680, и 655360. Итак, это 16 расширений, которые вам просто не нужно делать, если вы знаете, что получите 1000000 записей. Если вы -не- preallocate, он все равно будет работать нормально, просто будет немного медленнее.
5. Хорошо, понял, спасибо. Я не знал, что все, что он делал, все время удваивалось. Определенно должно помочь работать немного быстрее, если я переопределю это. Поскольку я пытаюсь ускорить процесс в первую очередь, тогда имело бы смысл делать это только таким образом.
Ответ №2:
Используется add
для вставки объектов в список.
Кроме того, то, как ваш код структурирован сейчас, вы получите a NullPointerException
при попытке вызова add
, потому что вызываемый вами конструктор никогда не инициализирует список.
Учитывая качество вашего кода, я настоятельно рекомендую прочитать «Изучение языка Java«.