Insertion Sort LinkedList Java - java

I'm trying to write an Insertion sort for a LinkedList, I have got a working method but it is incredibly slow. Over an hour to add&sort 50,000 elements.
public void insert(Custom c)
{
int i = 0;
for (i = 0; i < list.size(); i++)
{
if(list.get(i).compareTo(c) > 0 )
{
list.add(i,c);
return;
}
}
list.add(c);
}
I know i could use Collections.Sort but for this assignment I am required to write my own LinkedList. I'm not asking for a full solution just some pointers.

First of all, insertion sort on a List is going to be slow (O(N^2)) ... no matter how you do it. But you appear to have implemented it as O(N^3).
Here is your code ... which will be called N times, to add each list element.
public void insert(Entry e)
{
int i = 0;
for (i = 0; i < list.size(); i++) // HERE #1
{
if(list.get(i).compareTo(e) > 0 ) // HERE #2
{
list.add(i,e); // HERE #3
return;
}
}
list.add(e); // HERE #4
}
At "HERE #1" we iterate up to M times where M is the current (partial) list length; i.e. O(M). This is inherent in an insertion sort. However, depending on how you implemented the size() method, you could have turned the iteration into a O(M^2) sequence of operations. (The LinkedList.size() method just returns the value of a size variable. No problem here. But if size() counted the elements ... )
At "HERE #2" we have a fetch and a comparison. The comparison (compareTo(...)) is cheap, but the get(i) operation on a linked list involves traversing the list from the beginning. That is an O(M) operation. And since you make the get(i) call O(M) times per insert call, this makes the call O(M^2) and the sort O(N^3).
At "HERE #3" the add(i,e) repeats the list traversal of the previous get(i) call. But that's not so bad because you only execute that add(i,e) call once per insert call. So the overall complexity is not affected.
At "HERE #4" the add() operation could be either O(1) or O(M) depending on how it is implemented. (For LinkedList.add() it is O(1) because the list data structure keeps a reference to the last node of the list.) Either way, overall complexity is not affected.
In short:
The code at #2 definitely make this an O(N^3) sort.
The code at #1 could also make it O(N^3) ... but not with the standard LinkedList class.
So what to do?
One approach is to recode the insert operation so that it traverses the list using the next and prev fields, etcetera directly. There should not be calls to any of the "higher level" list operations: size, get(i), add(e) or add(i, e).
However, if you are implementing this by extending or wrapping LinkedList, this is not an option. Those fields are private.
If you are extending or wrapping LinkedList, then the solution is to use the listIterator() method to give you a ListIterator, and use that for efficient traversal. The add operation on a ListIterator is O(1).
If (hypothetically) you were looking for the fastest way to sort a (large) LinkedList, then the solution is to use Collections.sort. Under the covers, that method copies the list contents to an array, does an O(NlogN) sort on the array, and reconstructs the list from the sorted array.

According to this response, you should use ListIterator.add() instead of List.add due to the better performance.

What about using a faster sorting algorithm?
Here is something known as QuickSort. Its way faster then normal sorts for larger data sets. QuickSort has a average case of O(nlogn) while insertion only has a average case of O(n^2). Big difference isn't it?
Sample implementation
QuickSort Class
import java.util.*;
public class QuickSort{
public static void swap(int A[] , int x, int y){
int temp = A[x];
A[x] = A[y];
A[y] = temp;
}
public static int[] QSort(int A[],int L, int U){
Random randomGenerator = new Random();
if ( L >= U){
return A;
}
if (L < U) {
/*
Partion the array around the pivot, which is eventually placed
in the correct location "p"
*/
int randomInt = L + randomGenerator.nextInt(U-L);
swap(A,L,randomInt);
int T = A[L];
int p = L;
for(int i= L+1; i<= U; i++){
if (T > A[i]){
p = p+1;
swap(A,p,i);
}
}
/* Recursively call the QSort(int u, int l) function, this deals with
the upper pointer first then the lower.
*/
swap(A,L,p);
QSort(A,p+1,U);
QSort(A,L, p-1);
}
return A;
}
}
Sample Main
import java.util.*;
public class Main{
public static void main(String [] args){
int[] intArray = {1,3,2,4,56,0,4,2,4,7,80,120,99,9,10,67,101,123,12,-1,-8};
System.out.printf("Original Array was:\n%s\n\n",Arrays.toString(intArray));
System.out.printf("Size of Array is: %d\n\n",intArray.length);
QuickSort.QSort(intArray, 0, intArray.length - 1);
int num = Integer.parseInt(args[0]);
System.out.println("The sorted array is:");
System.out.println(Arrays.toString(intArray));
}
}
The above example will sort an Int array but you can easily edit it to sort any object(for example Entry in your case). Ill let you figure that out yourself.
Good Luck

list.add(e) and list.get(e) will take o(n) each time they are called. You should avoid to use them when you travel your list.
Instead, if you have to write your own linked list you should keep track of the elements you are traveling. by replacing the operation i++ and get(i) by elem = elem.next or elem = elem.getnext(), (maybe something else depending on how you implemented your linked list). Then you add an element by doing:
elem.next.parent = e;
e.next = elem.next;
elem.next = e;
e.parent = elem;
here my example works for a doubly linked list and elem represent the element in the linked list you are currently comparing your object you want to add.

Related

Finding the duplicates in the array

So here is this function that has 2 arguments given that is the array and the size of array and we have to return the answer in form of Arraylist.
I wrote this code but it was giving me time limit exceeded error and I was solving this as a problem on geeksforgeeks but I am not getting why is it giving time limit exceeded error. Thank you!
public static ArrayList<Integer> duplicates(int arr[], int n) {
Arraylist<Integer> arrList = new ArrayList<>();
Arrays.sort(arr);
for(int i=0; i<n; i++) {
if(arr[i] == arr[i+1] && !arrList.contains(arr[i])) {
arrList.add(arr[i]);
}
}
if(arrList.isEmpty()) {
arrList.add(-1);
}
return arrList;
}
I think expected time complexity to solve this problem is o(n) but you used sorting that's why its time complexity is o(nlogn). so you can use Treemap (which stores values in sorted order) to solve this problem in o(n) time complexity.
class Solution {
public static ArrayList<Integer> duplicates(int arr[], int n) {
TreeMap <Integer,Integer> map= new TreeMap<>();
ArrayList <Integer> ans= new ArrayList<>();
for(int i=0;i<n;i++){
map.put(arr[i],map.getOrDefault(arr[i],0)+1);
}
for(int key : map.keySet()){
if(map.get(key)>1){
ans.add(key);
}
}
if (ans.size()==0){
ans.add(-1);
return ans;
}
return ans;
}
}
You don't need sort as sorting has higher complexity O(nlog(n)).
Not sure what are the constraints and instructions for this question, but if you really don't have problem using extra space, you can use another array list, navigate through all the elements in the arr and put it to the some list called temp and check if number is already in the temp . Code reference is given below :
List<Integer> result = new ArrayList<>();
List<Integer> temp = new ArrayList<>();
int n = arr.length; // or you already passed n
for(int i=0;i<n;i++){
if(!temp.contains(arr[i])) {
temp.add(arr[i]);
}
else {
result.add(arr[i]);
}
}
return result;
This will be done at O(n) for both time and space complexity.
Of course, if you want to achieve the result without using extra space, you've to use another approach.
Condition arr[i] == arr[i+1] would cause an exception during the last iteration step (when i=n-1) with 100% certainty because i+1 will refer to the index that doesn't exist. You need to get rid of it.
contains() check on a List is expensive, it has O(n) time complexity. Which results in the overall quadratic O(n^2) time complexity of your solution.
As #Scary Wombat has pointed out in the comment, you can use HashSet to check whether the element was previously encountered or not. It would also eliminate the need for sorting the data and time complexity of the solution would be linear O(n).
In case if you have a requirement the result should be sorted, then it'll be more efficient to sort the resulting list (because it would contain fewer data than the given array).
public static List<Integer> duplicates(int[] arr, int n) {
Set<Integer> seen = new HashSet<>();
List<Integer> duplicates = new ArrayList<>();
for (int i = 0; i < n; i++) {
int next = arr[i];
if (!seen.add(next)) {
duplicates.add(next);
}
}
if (duplicates.isEmpty()) {
duplicates.add(-1);
}
// duplicates.sort(null); // uncomment this Line ONLY if results required to be in sorted order
return duplicates;
}
Sidenotes:
Don't use concrete classes like ArrayList as a return type, type of variable, method parameter, etc. Leverage abstractions, write the code against interfaces like List, Set, etc. If coding platform wants you to return an ArrayList, that unfortunate - leave the type as is, but keep in mind that it's not the way to go. See What does it mean to "program to an interface"?
Avoid using C-style of array declaration int arr[]. Because it mixes the variable name and the type, which might look confusing. int[] arr is preferable.

Java LinkedList : remove from to to

I have a java.util.LinkedList containing data logically like
1 > 2 > 3 > 4 > 5 > null
and I want to remove elements from 2 to 4 and make the LinkedList like this
1 > 5 > null
In reality we should be able to achieve this in O(n) complexity considering you have to break chain at 2 and connect it to 5 in just a single operation.
In Java LinkedList I am not able to find any function which lets remove chains from linkedlist using from and to in a single O(n) operation.
It only provides me an option to remove the elements individually (Making each operation O(n)).
Is there anyway I can achieve this in just a single operation (Without writing my own List)?
One solution provided here solves the problem using single line of code, but not in single operation.
list.subList(1, 4).clear();
The question was more on algorithmic and performance. When I checked the performance, this is actually slower than removing the element one by one. I am guessing this solution do not actually remove an entire sublist in o(n) but doing that one by one for each element (each removal of O(n)). Also adding extra computation to take the sublist.
Average of 1000000 computations in ms:
Without sublist = 1414
With the provided sublist solution : = 1846**
The way to do it in one step is
list.subList(1, 4).clear();
as documented in the Javadoc for java.util.LinkedList#subList(int, int).
Having checked the source code, I see that this ends up removing the elements one at a time. subList is inherited from AbstractList. This implementation returns a List that simply calls removeRange on the backing list when you invoke clear on it. removeRange is also inherited from AbstractList and the implementation is
protected void removeRange(int fromIndex, int toIndex) {
ListIterator<E> it = listIterator(fromIndex);
for (int i=0, n=toIndex-fromIndex; i<n; i++) {
it.next();
it.remove();
}
}
As you can see, this removes the elements one at a time. listIterator is overridden in LinkedList, and it starts by finding the first node by following chains either by following links from the start of the list or the end (depending on whether fromIndex is in the first or second half of the list). This means that list.subList(i, j).clear() has time complexity
O(j - i + min(i, list.size() - i)).
Apart from the case when the you are better off starting from the end and removing the elements in reverse order, I am not convinced there is a solution that is noticeably faster. Testing the performance of code is not easy, and it is easy to be drawn to false conclusions.
There is no way of using the public API of the LinkedList class to remove all the elements in the middle in one go. This surprised me, as about the only reason for using a LinkedList rather than an ArrayList is that you are supposed to be able to insert and remove elements from the middle efficiently, so I thought this case worth optimising (especially as it's so easy to write).
If you absolutely need the O(1) performance that you should be able to get from a call such as
list.subList(1, list.size() - 1)).clear();
you will either have to write your own implementation or do something fragile and unwise with reflection like this:
public static void main(String[] args) {
LinkedList<Integer> list = new LinkedList<>();
for (int a = 0; a < 5; a++)
list.add(a);
removeRange_NEVER_DO_THIS(list, 2, 4);
System.out.println(list); // [0, 1, 4]
}
public static void removeRange_NEVER_DO_THIS(LinkedList<?> list, int from, int to) {
try {
Method node = LinkedList.class.getDeclaredMethod("node", int.class);
node.setAccessible(true);
Object low = node.invoke(list, from - 1);
Object hi = node.invoke(list, to);
Class<?> clazz = low.getClass();
Field nextNode = clazz.getDeclaredField("next");
Field prevNode = clazz.getDeclaredField("prev");
nextNode.setAccessible(true);
prevNode.setAccessible(true);
nextNode.set(low, hi);
prevNode.set(hi, low);
Field size = LinkedList.class.getDeclaredField("size");
size.setAccessible(true);
size.set(list, list.size() - to + from);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
To remove the middle elements in a single operation (method call) you could subclass java.util.LinkedList and then expose a call to List.removeRange(int, int):
list.removeRange(1, 4);
(Credit to the person who posted this answer then removed it. :)) However, even this method calls ListIterator.remove() n times.
I do not believe there is a way to remove n consecutive entries from a java.util.LinkedList without performing n operations under the hood.
In general removing n consecutive items from any linked list seems to require O(n) operations as one must traverse from the start index to the end index one item at a time - inherently - in order to find the next list entry in the modified list.

Inserting into Sorted LinkedList Java

I have this code below where I am inserting a new integer into a sorted LinkedList of ints but I do not think it is the "correct" way of doing things as I know there are singly linkedlist with pointer to the next value and doubly linkedlist with pointers to the next and previous value. I tried to use Nodes to implement the below case but Java is importing this import org.w3c.dom.Node (document object model) so got stuck.
Insertion Cases
Insert into Empty Array
If value to be inserted less than everything, insert in the beginning.
If value to be inserted greater than everything, insert in the last.
Could be in between if value less than/greater than certain values in LL.
import java.util.*;
public class MainLinkedList {
public static void main(String[] args) {
LinkedList<Integer> llist = new LinkedList<Integer>();
llist.add(10);
llist.add(30);
llist.add(50);
llist.add(60);
llist.add(90);
llist.add(1000);
System.out.println("Old LinkedList " + llist);
//WHat if you want to insert 70 in a sorted LinkedList
LinkedList<Integer> newllist = insertSortedLL(llist, 70);
System.out.println("New LinkedList " + newllist);
}
public static LinkedList<Integer> insertSortedLL(LinkedList<Integer> llist, int value){
llist.add(value);
Collections.sort(llist);
return llist;
}
}
If we use listIterator the complexity for doing get will be O(1).
public class OrderedList<T extends Comparable<T>> extends LinkedList<T> {
private static final long serialVersionUID = 1L;
public boolean orderedAdd(T element) {
ListIterator<T> itr = listIterator();
while(true) {
if (itr.hasNext() == false) {
itr.add(element);
return(true);
}
T elementInList = itr.next();
if (elementInList.compareTo(element) > 0) {
itr.previous();
itr.add(element);
System.out.println("Adding");
return(true);
}
}
}
}
This might serve your purpose perfectly:
Use this code:
import java.util.*;
public class MainLinkedList {
private static LinkedList<Integer> llist;
public static void main(String[] args) {
llist = new LinkedList<Integer>();
addValue(60);
addValue(30);
addValue(10);
addValue(-5);
addValue(1000);
addValue(50);
addValue(60);
addValue(90);
addValue(1000);
addValue(0);
addValue(100);
addValue(-1000);
System.out.println("Linked List is: " + llist);
}
private static void addValue(int val) {
if (llist.size() == 0) {
llist.add(val);
} else if (llist.get(0) > val) {
llist.add(0, val);
} else if (llist.get(llist.size() - 1) < val) {
llist.add(llist.size(), val);
} else {
int i = 0;
while (llist.get(i) < val) {
i++;
}
llist.add(i, val);
}
}
}
This one method will manage insertion in the List in sorted manner without using Collections.sort(list)
You can do it in log (N) time Complexity simply. No need to iterate through all the values. you can use binary search to add value to sorted linked list.just add the value at the position of upper bound of that function.
Check code... you may understand better.
public static int ubound(LinkedList<Integer> ln, int x) {
int l = 0;
int h = ln.size();
while (l < h) {
int mid = (l + h) / 2;
if (ln.get(mid) <= x) l = mid + 1;
else h = mid;
}
return l;
}
public void solve()
{
LinkedList<Integer> ln = new LinkedList<>();
ln.add(4);
ln.add(6);
ln.add(ubound(ln, 5), 5);
out.println(ln);
}
Output : [4, 5, 6]
you can learn about binary search more at : https://www.topcoder.com/community/data-science/data-science-tutorials/binary-search/
#Atrakeur
"sorting all the list each time you add a new element isn't efficient"
That's true, but if you need the list to always be in a sorted state, it is really the only option.
"The best way is to insert the element directly where it has to be (at his correct position). For this, you can loop all the positions to find where this number belong to"
This is exactly what the example code does.
"or use Collections.binarySearch to let this highly optimised search algorithm do this job for you"
Binary search is efficient, but only for random-access lists. So you could use an array list instead of a linked list, but then you have to deal with memory copies as the list grows. You're also going to consume more memory than you need if the capacity of the list is higher than the actual number of elements (which is pretty common).
So which data structure/approach to take is going to depend a lot on your storage and access requirements.
[edit]
Actually, there is one problem with the sample code: it results in multiple scans of the list when looping.
int i = 0;
while (llist.get(i) < val) {
i++;
}
llist.add(i, val);
The call to get(i) is going to traverse the list once to get to the ith position. Then the call to add(i, val) traverses it again. So this will be very slow.
A better approach would be to use a ListIterator to traverse the list and perform insertion. This interface defines an add() method that can be used to insert the element at the current position.
Have a look at com.google.common.collect.TreeMultiset.
This is effectively a sorted set that allows multiple instances of the same value.
It is a nice compromise for what you are trying to do. Insertion is cheaper than ArrayList, but you still get search benefits of binary/tree searches.
Linked list isn't the better implementation for a SortedList
Also, sorting all the list each time you add a new element isn't efficient.
The best way is to insert the element directly where it has to be (at his correct position).
For this, you can loop all the positions to find where this number belong to, then insert it, or use Collections.binarySearch to let this highly optimised search algorithm do this job for you.
BinarySearch return the index of the object if the object is found in the list (you can check for duplicates here if needed) or (-(insertion point) - 1) if the object isn't allready in the list (and insertion point is the index where the object need to be placed to maintains order)
You have to find where to insert the data by knowing the order criteria.
The simple method is to brute force search the insert position (go through the list, binary search...).
Another method, if you know the nature of your data, is to estimate an insertion position to cut down the number of checks. For example if you insert 'Zorro' and the list is alphabetically ordered you should start from the back of the list... or estimate where your letter may be (probably towards the end).
This can also work for numbers if you know where they come from and how they are distributed.
This is called interpolation search: http://en.wikipedia.org/wiki/Interpolation_search
Also think about batch insert:
If you insert a lot of data quickly you may consider doing many insertions in one go and only sort once afterwards.
Solution of Amruth, simplified:
public class OrderedList<T extends Comparable<T>> extends LinkedList<T> {
private static final long serialVersionUID = 1L;
public boolean orderedAdd(T element) {
ListIterator<T> itr = listIterator();
while(itr.hasNext()) {
if (itr.next().compareTo(element) > 0) {
itr.previous();
break;
}
}
itr.add(element);
}
}
Obviously it's O(n)

How to sort an ArrayList

All I need is the simplest method of sorting an ArrayList that does not use the in-built Java sorter. Currently I change my ArrayList to an Array and use a liner sorting code, but I later need to call on some elements and ArrayLists are easier to do that.
you can use anonymous sort.
Collections.sort(<ArrayList name>, Comparator<T>() {
public int compare(T o1, T o2) {
.....
....
}
});
where T is the type you want to sort (i.e String, Objects)
and simply implement the Comparator interface to your own needs
Assuming an ArrayList<String> a...
Easiest (but I'm guessing this is what you're saying you can't use):
Collections.sort(a);
Next easiest (but a waste):
a = new ArrayList<String>(new TreeSet<String>(a));
Assuming "in-built sort" refers to Collections.sort() and you are fine with the sorting algorithm you have implemented, you can just convert your sorted array into an ArrayList
ArrayList list = new ArrayList(Arrays.asList(sortedArray));
Alternatively, you can rewrite your sorting algorithm to work with a List (such as an ArrayList) instead of an array by using the get(int index) and set(int index, E element) methods.
Sorting Arguments passed through Command prompt; without using Arrays.sort
public class Sort {
public static void main(String args[])
{
for(int j = 0; j < args.length; j++)
{
for(int i = j + 1; i < args.length; i++)
{
if(args[i].compareTo(args[j]) < 0)
{
String t = args[j];
args[j] = args[i];
args[i] = t;
}
}
System.out.println(args[j]);
}
}
}
By using Array.sort
import java.util.*;
public class IntegerArray {
public static void main(String args[])
{
int[] num=new int[]{10, 15, 20, 25, 12, 14};
Arrays.sort(num);
System.out.println("Ascending order: ");
for (int i=0; i<num.length; i++)
System.out.print(num[i] + " ");
}
}
Collections.sort(List);
If i remember correctly when you pull an element out of the middle of an arrayList it moves the rest of the elements down automaticly. If you do a loop that looks for the lowest value and pull it out then place it at the end of the arrayList. On each pass i-- for the index. That is use one less. So on a 10 element list you will look at all 10 elements take the lowest one and append it to the end. Then you will look at the first nine and take the lowest of it out and append it to the end. Then the first 8 and so on till the list is sorted.
Check for Comparator in java. You can implement your own sorting using this and use Collections.sort(..) to sort the arraylist using your own Comparator
If you are meant to sort the array yourself, then one of the simplest algorithms is bubble sort. This works by making multiple passes through the array, comparing adjacent pairs of elements, and swapping them if the left one is larger than the right one.
Since this is homework, I'll leave it to you to figure out the rest. Start by visualizing your algorithm, then think about how many passes your algorithm needs to make, and where it needs to start each pass. Then code it.
You also need to understand and solve the problem of how you compare a pair of array elements:
If the elements are instances of a primitive type, you just use a relational operator.
If the elements are instances of reference types, you'll need to use either the Comparable or Comparator interface. Look them up in the javadocs. (And looking them up is part of your homework ...)
Here is a "simple" quicksort implementation:
public Comparable<Object>[] quickSort(Comparable<Object>[] array) {
if (array.length <= 1) {
return array;
}
List<Comparable<Object>> less = new ArrayList<Comparable<Object>>();
List<Comparable<Object>> greater = new ArrayList<Comparable<Object>>();
Comparable<Object> pivot = array[array.length / 2];
for (int i = 0;i < array.length;i++) {
if (array[i].equals(pivot)) {
continue;
}
if (array[i].compareTo(pivot) <= 0) {
less.add(array[i]);
} else {
greater.add(array[i]);
}
}
List<Comparable<Object>> result = new ArrayList<Comparable<Object>>(array.length);
result.addAll(Arrays.asList(quickSort(less.toArray(new Comparable<Object>[less.size()]))));
result.add(pivot);
result.addAll(Arrays.asList(quickSort(greater.toArray(new Comparable<Object>[greater.size()]))));
return result.toArray(new Comparable<Object>[result.size()]);
}
The last operations with arrays and list to build the result can be enhanced using System.arraycopy.

How can I make a resizable array in Java?

What is the best way to do a resizable array in Java? I tried using Vector, but that shifts all elements over by when when you do an insert, and I need an array that can grow but the elements stay in place. I'm sure there's a simple answer for this, but I still not quite sure.
As an alternative, you could use an ArrayList. It is a resizable-array implementation of the List interface.
Usage (using String):
List<String> myList = new ArrayList<String>();
myList.add("a");
myList.add("c");
myList.add("b");
The order will be just like you put them in: a, c, b.
You can also get an individual item like this:
String myString = myList.get(0);
Which will give you the 0th element: "a".
Like Sanjo pointed out: "An array is a static datastructure, so they can't grow". The list interface can by backed by an array(for example ArrayList like Kevin pointed out in his post). When the list structure is full and a new item has to be added to the list. Then the structure first creates a new array which can contain the old elements plus the new element which has to be added to the list.
The list interface has a different implementations which all have there pros/cons and you should pick the one best solving your problem-set. Below I will try to give a short summary when to use which implementation:
Not thread-safe implementations:
ArrayList: Resizable-array implementation of the List interface. You should use this implementation when you are doing a lot of size, isEmpty, get, set, iterator, and listIterator operations run in constant time. The add operation runs in amortized constant time, that is, adding n elements requires O(n) time. I think you should use this implementation when doing more lookups(get()) then adding items to list(add()).
LinkedList: This implementation is not backup by an array but "links" the nodes together. In my opinion you should use this implementation when you are doing more add() then get().
Thread-safe implementations:
Be aware that these list implementations aren't thread-safe which means it is possible to get race conditions when accesing them from multiple threads. If you want to use List implementations from multiple threads I would advise you to study the java.util.concurrent package and use implementation from that class.
You probably should use ArrayList instead of Vector for reasons explained in other answers.
However ...
I tried using Vector, but that shifts all elements over by when when you do an insert, and I need an array that can grow but the elements stay in place.
When you do an insertElementAt(pos, elem), you have specifically asked for the element shifting. If you don't want the elements to be shifted, you should use set(pos, elem) instead. Or if you want to add the element at the end of the vector, you can also use add(elem).
Incidentally, the previous paragraph applies to all implementations of List, not just Vector, though the implementation details and performance vary across the different kinds of List.
I tried using Vector, but that shifts all elements over by when when you do an insert, and I need an array that can grow but the elements stay in place.
You probably want to use ArrayList instead of Vector.
They both provide about the same interface, and you can replace elements with both of them by calling set(idx, element). That does not do any shifting around. It also does not allow you to grow the array, though: You can only insert at already occupied positions (not beyond the current size of the array), to add new elements at the end you have to use add(element).
The difference between ArrayList and Vector is that Vector has synchronization code which you most likely do not need, which makes ArrayList a little faster.
If you want to operate array data after all element had already inserted or deleted, there is a way that try to create a LinkedList or ArrayList, its simply resize, after the data input is finished, you can transfer the ArrayList to an Array, then do all the things you normally to Array.
ArrayList and LinkedList
Space Complexity:
a) ArrayList:
Allocates a chunk of memory when you initialize and doubles everytime it reaches it max size whenever you add an element dynamically.
b) LinkedList:
It allocates memory only everytime you add an item to the list.
Runtime Complexity:
a) ArrayList:
Search is faster, insertion and deletion is slower compared to linked list
b) LinkedList:
Insertion and deletion is faster, search is slower compared to array list
An array cannot be resized dynamically in Java. The solution to this is using ArrayList or creating another temporary array and then assign it.
You can find tutorials about ArrayList, but if you just want custom ResizableArray in Java. Here's it is. But it's NOT recommend to use! It's just a FAKE resizable array and heap memory will be increased when you create too many objects. This is just to show you the idea.
The Interface
public interface Resizable<T> {
void add(T data);
int delete(int index);
int size();
void print();
}
Implementation Class
public class ResizeableImpl<T> implements Resizable<T> {
private Object[] temp = null;
private Object[] originals = new Object[0];
#Override
public void add(T data) {
Object[] temp = new Object[originals.length+1];
for (int i=0; i<originals.length; i++) {
temp[i]=originals[i];
}
temp[originals.length]=data;
originals=temp;
}
#Override
public int delete(int index) {
int success=0;
switch (originals.length) {
case 0: //No Data to delete
success=0;
break;
case 1: //One Data is delete and so no data, too!
originals = new Object[0];
success = 1;
break;
default: //>=2
int count=0;
originals[index]=null;
temp = new Object[originals.length-1];
for (int i=0; i<originals.length; i++) {
if (originals[i]!=null)
temp[count++]=originals[i];
}
originals = temp;
success = 1;
}
return success;
}
#Override
public int size() {
return originals.length;
}
#Override
public void print() {
StringBuilder sb = null;
if (originals.length==0) {
System.out.println("No data available!");
return;
}
for (int i=0; i<originals.length; i++) {
if (sb==null) {
sb = new StringBuilder();
sb.append(originals[i]);
}
else {
sb.append(", "+originals[i]);
}
}
sb.append(".");
System.out.println(sb.toString());
}
}
Main method
public class App {
public static void main(String[] args) {
//Program to interfaces, not implementations
Resizable<Integer> obj = new ResizeableImpl<>();
obj.add(13);
obj.add(20);
obj.add(17);
obj.add(25);
obj.add(100);
obj.add(12);
obj.print();
int result = obj.delete(2); //This will delete 17.
if (result==1) {
System.out.println("Deletion is successful!");
}
obj.print();
obj.delete(3); //This will delete 100.
obj.print();
}
}
Output
13, 20, 17, 25, 100, 12.
Deletion is successful!
13, 20, 25, 100, 12.
13, 20, 25, 12.
Use either ArrayList or LinkedList.
Using wonderful classes in Collections framework is the better than using arrays.
But in case your question is from a "quizzing" perspective, here is what you should do.
Create your own resize method such as:
int[] oldArray = {1,2,3};
int oldSize = java.lang.reflect.Array.getLength(oldArray);
Class elementType = oldArray.getClass().getComponentType();
Object newArray = java.lang.reflect.Array.newInstance(
elementType,newSize);
int preserveLength = Math.min(oldSize,newSize);
if (preserveLength > 0)
System.arraycopy (oldArray,0,newArray,0,preserveLength);
oldArray = newArray;

Categories

Resources