List Introduction - 列表简介
Made by Mike_Zhang
数据结构与算法主题:
1. Introduction to List
List is a more general Abstract Data Type than Stack and Queue mentioned before, which has more general method in adding or removing elements at arbitrary positions.
Locating an element is very important in linear data structure.
In Array, it is easy to locate with a integer index.
Index: for an element
e
, its index in a sequence is the number of elements before it in that sequence.
In LinkedList, it is not easy to locate an element with a integer index, since we have to traverse all elements before that element.
Based on index, Java has a more general interface, java.util.List
.
2. List ADT
Some methods in java.util.List
Interface:
size()
: Returns the number of elements in the list.isEmpty()
: Returnstrue
if the list contains no elements,false
otherwise.get(i)
: Returns the element at the specified position in the list, error if the index is out of range.set(i,e)
: Replace the element at indexi
withe
, return the old element in that position, error if the index is out of range.add(i,e)
: Inserts the elemente
at indexi
by moving all the elements afteri
one position to the right, error if the index is out of range.remove(i)
: Removes and return the element at indexi
by moving all the elements afteri
one position to the left, error if the index is out of range.
Notice:
- The index of an element may be changed after adding or removing an element.
- Adding and removing an element requires shifting the elements after the index.
Some List ADT Java implementations:
1 |
|
3. List Implementations
List ADT can be easily implemented by Array and optimized by Dynamic Array.
3.1 Array Implementation
Implementation in Array is a intuitive way for List implementation.
For method get(i)
and set(i,e)
, they can be easily implemented by indexing the array, A[i]
.
However, for method add(i,e)
and remove(i)
, we need to shift the elements after index i
.
In above figure, (a) is the shifting process for adding an element into index i
; (b) is the shifting process for removing an element from index i
.
ArrayList Java implementation:
1 |
|
ArrayList Performance:
Method | Running time |
---|---|
size() |
$O(1)$ |
isEmpty() |
$O(1)$ |
get(i) |
$O(1)$ |
set(i,e) |
$O(1)$ |
add(i,e) |
$O(n)$ |
remove(i) |
$O(n)$ |
Advantages:
- Easy to implement.
- Constant time in getting and setting elements due to direct access.
Drawbacks:
- More time required to add and remove elements. Because all element after the position need to be shifted. On average, $\frac{n}{2}$ elements need to be shifted, which results in the time complexity of $O(n)$.
- The maximum capacity of the ArrayList is fixed, which means that it cannot be resized.
In fact, Java’s ArrayList has no pre-requisite on the capacity, which is implemented by the dynamic array.
3.2 Dynamic Array Implementation
Dynamic Array is still implemented by the traditional array with fixed capacity but with some special strategies.
Key points:
- Keep the internal array’s capacity greater than the current length of the array;
- If the array is full, Java requires a new and larger array, and copy all elements into the new array for extension.
- With enlarged ArrayList, more elements can be added.
So, the main step is to “enlarge” the array:
- Create a new
Array B
with larger capacity (Step a); - Set $B[0,1,2,…,n]=A[0,1,2,…,n]$ where $n$ is the current length of the
array A
(Step b); A = B
, Array A is now the reference to the new larger array (Step c).
Some optimization of ArrayList with Dynamic Array:
1 |
|
With the help of Dynamic Array, the List capacity will not be limited. However, user can also set a proper capacity in the constructor, which can improve the performance due to less resizing time.
4. Introduction to Positional List
There are two problems in traditional linear data structures:
- Numeric indices are not good for linked list because it need to traverse all elements from the beginning to that index, which is expensive.
- Index may be changed due to the insertion or deletion of elements.
The solution is the positional list, which can easily refer to any element in the sequence, as well as perform arbitrary insertions and deletions in $O(1)$.
Actually, the similar ADT is DoublyLinkedList, where all element are stored in the node who indicates element’s position. However, the
Node
field is private, which cannot be accessed by the user directly.
The solution is to create our own “Node” which is the Position.
5. Position ADT
Position ADT offers a more general way to describe the location of an element in the sequence. The association between the element and its position is immutable.
Position Interface only contains one method:
1 |
|
6. Positional List ADT
Positional List is a collection of Positions.
Methods defined in Positional List:
first()
: Return the position of the first element in the List, ornull
if the List is empty;last()
: Return the position of the last element in the List, ornull
if the List is empty;before(p)
: Return the position of the element immediately before the positionp
, ornull
ifp
is the first position;after(p)
: Return the position of the element immediately after the positionp
, ornull
ifp
is the last position;isEmpty()
: Returntrue
if the List is empty, otherwisefalse
;size()
: Return the number of elements in the List;addFirst(e)
: Insert an element to the front of the List, return the position of the new element;addLast(e)
: Insert an element to the end of the List, return the position of the new element;addBefore(p, e)
: Insert an element before the positionp
, return the position of the new element;addAfter(p, e)
: Insert an element after the positionp
, return the position of the new element;set(p, e)
: Replace the element at the positionp
withe
, return the element previously atp
;remove(p)
: Remove and return the element at the positionp
, invalidating positionp
;
Notice: “Return the position” means the position instance is returned, not the element inside.
PositionalList Java Interface:
1 |
|
7. Positional List Implementations
Positional List can be implemented by Doubly Linked List and pure Array.
7.1 Doubly Linked List Implementation
It is intuitive that the Doubly Linked List is used to implement PositionalList.
The Node reference in Doubly Linked List can be seen as the Position of the element.
However, the Node reference is private in Doubly Linked List, which cannot be accessed by the user directly. We need to design our own Node who implements Position.
Positional List Java Implementation:
1 |
|
Test:
1 |
|
Output:
1 |
|
Performance:
With the help of DoublyLinkedList, all methods in Positional List ADT run in $O(1)$ time in LinkedPositionalList.
7.2 Array Implementation
Since pure Array uses index for position, we have to store the block of [index, element]
inside to store the Position objects.
- When inserting and deleting elements, we have to update all shifted positions inside the block iteratively.
- Comparing with the Positional List, array implementation is slower due to shifting takes $O(n)$ time.
References
Goodrich, M., Tamassia, R., & O’reilly, A. (2014). Data Structures and Algorithms in Java, 6th Edition. John Wiley & Sons.
写在最后
List 相关的知识会继续学习,继续更新.
最后,希望大家一起交流,分享,指出问题,谢谢!
原创文章,转载请标明出处
Made by Mike_Zhang