2

I start with a rectangle, from this I need to be able to adjust the shape. (It's for bin packing).

To do this, I want to use a doubly-linked list since the article describing the algorithm makes also use of a doubly linked list.

This would allow me to go from a square to this for example: enter image description here

From a given vector, I need also to be able to recognize a point to the north and east: enter image description here

What I wonder, is the Java implementation of LinkedList good for this? I doubt because:

  1. There is no insertBefore and insertAfter method like there is with the wikipedia explanation, and those methods seems to be use full.

  2. There is no way to start traversing from a certain point. This looks quite performance heavy cause If I want to find the point upwards on a edge from a given vector, I have to Iterate from the start?

I have some more doubts but it's hard for me te explain. If it was easy for me to explain then I probably wouldn't be asking it in the first place.

clankill3r
  • 9,146
  • 20
  • 70
  • 126
  • 2
    Beware... iterating through an `ArrayList` (which is implemented with an array) may involve visiting more "nodes" that iterating your double linked list, but be faster since accessing the array involves less memory indirections. First, check if you **need** to improve the performance of your classes, and after that **measure** that your solution is indeed faster. – SJuan76 Nov 06 '14 at 10:49
  • 2
    Also, `insertBefore` and `insertAfter` should be trivial to program using any implementation of `java.util.List`. – SJuan76 Nov 06 '14 at 10:51
  • The `listIterator(int)` method allows you iterate in any direction from a certain point. – biziclop Nov 06 '14 at 11:26

3 Answers3

2

LinkedList is in most cases the worst choice for a list implemenation because it is really slow. You most propably want to use an ArrayList (http://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html) which is backed by an array.

This is much faster.

To point 1. You can use

list.add(int index, E element);

To insert before / after a given index. To insert before / after an element, use

list.indexOf(Object o)

to get the index of that element.

To point 2. This is specific to the linked list. Since the Array List is backed by an array, you can start traversing in "no time".

list.get(int index)

See also: When to use LinkedList over ArrayList?

Community
  • 1
  • 1
Mirco
  • 2,940
  • 5
  • 34
  • 57
2

There are many points in your question, I'll try to address them all:

List Implementation

Java actually has many implementations of the List interface. It is important to pick the right implementation for your use case. Some lists implement. Some List implementations also implement interfaces like Deque or Queue or RandomAccess and provide extra useful methods.

If the expected length of your list is large, it is also important to pick the implementation with the right performance characteristics for your usage patterns. Some implementations are better at dealing with random reads, random inserts, etc... If your lists are small though, you probably won't notice any performance difference.

The most common implementations are:

ArrayList

All the elements in the list are placed in a backing array. This is nice because it offers really fast random read access to elements. The complexity ArrayList::get(index) is O(1) (doesn't depend on the size of list). It is also fast to iterate over in both directions.

However ArrayList has a pretty bad random insert/delete performance. Adding or removing elements at the end of the list is a fast O(1) operation, but inserting or deleting anywhere else in the list is a much slower O(n), because all the elements in the array placed after the insertion point must be shifted right/left. The worst case for ArrayList is modifiying the beginning of the list.

Removing elements one by one while iterating using an Iterator is pretty bad: O(m*n) where n is the length of the list and m is the number of elements you are removing.

LinkedList

The java LinkedList is actually a doubly linked list. It has a bad random access performance O(n), but is fast to iterate over. Adding or removing items at the head or the tail of the list is a very fast O(1), but adding elements at random positions in the middle of the list is O(n), because the implementation must first follow all the links to find the insertion point before doing the insert. If you are going to insert many elements over a small random range, you can however gain a lot of performance by it on a sublist(), so that the number of links that need to be followed is reduced to the size of the sublist.

Removing elements one by one while iterating using an Iterator is o(m) where m is the number of elements you are removing (note that the length of the list is not a factor.

insertBefore, insertAfter

These operations described on the wikipedia page you linked are actually operations that are internal to any linked list, and are usually not part of the public API of the list. As you can see, those operations are described using Node instances, which are an internal implementation detail of a typical linked list.

In Java, you can use the various flavors of add() or addAll() and combine it with indexOf() or sublist() to achieve the same result and performance characteristics.

Iteration from an arbitrary point

In both cases, it is trivial from a code point of view to iterate on the list starting from an arbitrary point. You can use the listIterator() method to obtain an iterator that can iterate from a specific point in any direction.

You can also use the sublist(start, end) method, which returns a new List instance that is a view on the underlying list (ie: if you modify the list returned by subList(), it actually modifies the original list). So to iterate over elements 2-5, just do myList.sublist(2, 6).forEach(el -> doSomething(el))

LordOfThePigs
  • 11,050
  • 7
  • 45
  • 69
  • That is really smart about the sublist to gain performance. Thanks for your big answer. I was making use of: http://algs4.cs.princeton.edu/13stacks/DoublyLinkedList.java.html But I think I will switch to ArrayList now and after that maybe to java's implementation of a doubly-linked list. – clankill3r Nov 06 '14 at 13:11
1

Just because you are storing your objects in one structure does not stop you maintaining other structures that also contain your objects.

For traversal backwards and forwards I would probably use an ArrayList as it implements RandomAccess.

For searching for segments that intersect a horizontal/vertical line I would probably use two IntervalTrees.

Community
  • 1
  • 1
OldCurmudgeon
  • 64,482
  • 16
  • 119
  • 213
  • I looked at the IntervalTree but I don't really understand it. However it looks interesting. I might give it some more time later. Performance is not really a problem for now. First I should get it to work. – clankill3r Nov 06 '14 at 13:22