Binary-algorithm -> Insert String to sorted String-ArrayList
Hey all.
As far as I know this algorithm isn't there by default and I need it for my new project - because it will contain ArrayLists with a very large amount of Strings in them.
Therefore I thought that instead of sorting after every String is inserted, I'd rather come up with an algorithm that inserts the String to it's right place.
The idea is to simply used the binary search algorithm that halves the amount of options every time.
Unfortunately I have no idea how the "natural order"-sorting works, so I'm only doing the basic one (unless you guys have some easy optimization?) with .compareTo().
Now, I've tested this algorithm in all the ways I could think of:
- The list is empty
- The list has only identical Strings
- The list has only Strings with lower value than the String to insert
- The list has only Strings with higher value than the String to insert
- The list has many identical Strings
Now I know I may be asking a lot here:
Do any of you have advice of optimization? Perhaps obvious flaws? Or maybe even just things that I should test?
(Note: I know that a few if-sentences could contain less arguments - however, I want to be able to read it again later).
Additional Questions:
When this method is fully optimized, I'm considering making it take a String[] instead - and return a new one - since it gives a quicker performance (am I right about this?).
I recall that I could use the parameters (Comparable[] arr, Comparable x) - and it would work for other things than Strings as well. Is this correct?
Code:
[color="#3F5FBF"]/**
* <b>Requires</b>: List is sorted from A-Z-a-z <i>OR</i> z-a-Z-A<br \>
* <br \>
* Automatically determines whether your list is ascending or descending.<br \>
* <b>Note</b>: If all items in the arrayList are identical, the list order
* is assumed ascending.
*
* [color="#7F9FBF"]@[B]param[/B][/color] sortedList
* the String-ArrayList to insert to.
* [color="#7F9FBF"]@[B]param[/B][/color] toBeInserted
* the String to insert.
* [color="#7F9FBF"]@[B]author[/B][/color] Muskar
*/[/color]
[b][color="#7F0055"]public static void[/color][/b] insertToSorted(ArrayList<String> sortedList,
String toBeInserted) {
[b][color="#7F0055"]boolean[/color][/b] inserted = [b][color="#7F0055"]false[/color][/b];
[b][color="#7F0055"]if[/color][/b] (sortedList.size() == 0) {
sortedList.add(toBeInserted);
inserted = [b][color="#7F0055"]true[/color][/b];
}
[b][color="#7F0055"]int[/color][/b] left = 0;
[b][color="#7F0055"]int[/color][/b] right = sortedList.size() - 1;
[b][color="#7F0055"]int[/color][/b] middle = -1;
[b][color="#7F0055"]int[/color][/b] k;
[b][color="#7F0055"]boolean[/color][/b] ascending = [b][color="#7F0055"]true[/color][/b];
[b][color="#7F0055"]if[/color][/b] (sortedList.get(left).compareTo(sortedList.get(right)) > 0) {
ascending = [b][color="#7F0055"]false[/color][/b];
}
System.[color="#2A00FF"]out[/color].print([color="#2A00FF"]"The list is "[/color]);
[b][color="#7F0055"]if[/color][/b] (ascending) {
System.[color="#2A00FF"]out[/color].println([color="#2A00FF"]"ascending."[/color]);
} [b][color="#7F0055"]else[/color][/b] {
System.[color="#2A00FF"]out[/color].println([color="#2A00FF"]"descending."[/color]);
}
[b][color="#7F0055"]if[/color][/b] (ascending && !inserted) {
[color="#3F7F5F"]/*
* If the first String in the list has a greater value than
* toBeInserted then no search is required - and toBeInserted is
* then inserted to the first index.
*/[/color]
[b][color="#7F0055"]if[/color][/b] (sortedList.get(left).compareTo(toBeInserted) > 0) {
sortedList.add(left, toBeInserted);
inserted = [b][color="#7F0055"]true[/color][/b];
}
[color="#3F7F5F"]/*
* If the last String in the list has a lower/the same value than/as
* toBeInserted then no search is required - and toBeInserted is
* then inserted after the last index.
*/[/color]
[b][color="#7F0055"]else if[/color][/b] (sortedList.get(right).compareTo(toBeInserted) <= 0) {
sortedList.add(toBeInserted);
inserted = [b][color="#7F0055"]true[/color][/b];
}
[b][color="#7F0055"]while[/color][/b] (!inserted && left <= right) {
middle = (left + right) / 2;
k = sortedList.get(middle).compareTo(toBeInserted);
[b][color="#7F0055"]if[/color][/b] (left == right || left == right - 1) {
[b][color="#7F0055"]int[/color][/b] kNext = sortedList.get(middle + 1).compareTo(
toBeInserted);
[color="#3F7F5F"]// If there's only 1 option left in the end:[/color]
[b][color="#7F0055"]if[/color][/b] (left == right) {
[b][color="#7F0055"]if[/color][/b] (k < 0) {
sortedList.add(middle + 1, toBeInserted);
} [b][color="#7F0055"]else[/color][/b] if (k > 0) {
sortedList.add(middle, toBeInserted);
}
}
[color="#3F7F5F"]// If there's 2 options left in the end:[/color]
[b][color="#7F0055"]else if[/color][/b] (k <= 0 && kNext > 0) {
sortedList.add(middle + 1, toBeInserted);
} [b][color="#7F0055"]else if[/color][/b] (k < 0 && kNext <= 0) {
sortedList.add(middle + 2, toBeInserted);
} [b][color="#7F0055"]else if [/color][/b] (k > 0 && kNext > 0) {
sortedList.add(middle, toBeInserted);
}
inserted = [b][color="#7F0055"]true[/color][/b];
} [b][color="#7F0055"]else[/color][/b] {
[b][color="#7F0055"]if[/color][/b] (k == 0) {
[color="#3F7F5F"]/*
* This only happens if 'middle', during the search,
* finds a String in the list with the exact same value
* as toBeInserted.
*/[/color]
sortedList.add(middle, toBeInserted);
inserted = [b][color="#7F0055"]true[/color][/b];
} [b][color="#7F0055"]else[/color][/b] if (k > 0) {
right = middle - 1;
} [b][color="#7F0055"]else[/color][/b] if (k < 0) {
left = middle;
}
}
}
}
[b][color="#7F0055"]else if[/color][/b] (!ascending && !inserted) {
[color="#3F7F5F"]/*
* If the first String in the list has a lower/the same value
* than/as toBeInserted then no search is required - and
* toBeInserted is then inserted to the first index.
*/[/color]
[b][color="#7F0055"]if[/color][/b] (sortedList.get(left).compareTo(toBeInserted) <= 0) {
sortedList.add(left, toBeInserted);
inserted = [b][color="#7F0055"]true[/color][/b];
}
[color="#3F7F5F"]/*
* If the last String in the list has a greater value than
* toBeInserted then no search is required - and toBeInserted is
* then inserted after the last index.
*/[/color]
[b][color="#7F0055"]else if[/color][/b] (sortedList.get(right).compareTo(toBeInserted) > 0) {
sortedList.add(toBeInserted);
inserted = [b][color="#7F0055"]true[/color][/b];
}
[b][color="#7F0055"]while[/color][/b] (!inserted && left <= right) {
middle = (left + right) / 2;
k = sortedList.get(middle).compareTo(toBeInserted);
[b][color="#7F0055"]if[/color][/b] (left == right || left == right - 1) {
[b][color="#7F0055"]int[/color][/b] kNext = sortedList.get(middle + 1).compareTo(
toBeInserted);
[color="#3F7F5F"]// If there's only 1 option left in the end:[/color]
[b][color="#7F0055"]if[/color][/b] (left == right) {
[b][color="#7F0055"]if[/color][/b] (k > 0) {
sortedList.add(middle + 1, toBeInserted);
} [b][color="#7F0055"]else if[/color][/b] (k < 0) {
sortedList.add(middle, toBeInserted);
}
}
[color="#3F7F5F"]// If there's 2 options left in the end:[/color]
[b][color="#7F0055"]else if[/color][/b] (k > 0 && kNext <= 0) {
sortedList.add(middle + 1, toBeInserted);
} [b][color="#7F0055"]else if[/color][/b] (k <= 0 && kNext <= 0) {
sortedList.add(middle + 2, toBeInserted);
} [b][color="#7F0055"]else if[/color][/b] (k > 0 && kNext > 0) {
sortedList.add(middle + 2, toBeInserted);
}
inserted = [b][color="#7F0055"]true[/color][/b];
} [b][color="#7F0055"]else[/color][/b] {
[b][color="#7F0055"]if[/color][/b] (k == 0) {
[color="#3F7F5F"]/*
* This only happens if 'middle', during the search,
* finds a String in the list with the exact same value
* as toBeInserted.
*/[/color]
sortedList.add(middle, toBeInserted);
inserted = [b][color="#7F0055"]true[/color][/b];
} [b][color="#7F0055"]else if[/color][/b] (k < 0) {
right = middle - 1;
} [b][color="#7F0055"]else[/color][/b] {
left = middle;
}
}
}
}
}