A list stores a sequence of $n$ elements. Supported operations:
len(l)
: return the number of items in the listl[i]
: return the item at position i
l[i] = e
: replace the item at position i
l.prepend(e)
: adds e
to the beginning of the listl.append(e)
: appends e
to the end of the listl1 + l2
: concatenates two listsdel l[i]
: delete the element at position i
len([1,2,3])
3
l = [1,2,3,6,7]; l[3]
6
l = [1,2,3]; l[1] = 15
[1,15,3]
l = [1,2,3]; del l[1]
[1,3]
[1,2,3] + [4,1,3]
[1,2,3,4,1,3]
l = [1,2,3,6,7]; l.prepend(15)
[15,1,2,3,6,7]
l = [1,2,3,6,7]; l.append(15)
[1,2,3,6,7,15]
len(a)
- return the number of elements in the arrayl[i]
- return element at position i
l[i] = e
- replace the element at position i
with e
class ArrayList:
def __init__(self,n=10):
self.data = MyArray(n)
self.len = 0
def extend(self, newsize):
newa = MyArray(newsize)
for i in range(0, self.len):
newa[i] = self.data[i]
self.data = newa
def __len__(self):
return self.len
def __getitem__(self, idx):
return self.data[idx]
def __setitem__(self, idx, value):
self.data[idx] = value
def append(self, value):
if len(self.data) <= self.len:
self.extend(len(self.data) + 1)
self.data[self.len] = value
self.len += 1
def prepend(self, value):
if len(self.data) <= self.len:
self.extend(len(self.data) + 1)
for i in range(0, self.len):
self.data[i+1] = self.data[i]
self.data[0] = value
self.len += 1
def __delitem__(self, idx):
for i in range(idx+1, self.len):
self.data[i-1] = self.data[i]
self.len += -1
len(l)
, l[i]
, l[i] = e
extend
l.append(e)
:
O(n)
because of extend
l.prepend(e)
:
O(n)
because of extend
del l[i]
: delete the element at position i
def append(self, value):
if len(self.data) <= self.len:
self.extend(min(1,2 * len(self.data)))
self.data[self.len] = value
self.len += 1
$$T(n) = \sum_{i=0}^{i} 2^i$$ $= 2^{m+1} - 1$ (proof to follow) $$= 2 n - 1 = O(n)$$
We proof this claim by induction
Base case: $m=0$: $$\sum_{i=0}^{0} 2^i = 2^0 = 1 = 2^{2} - 1$$
val
store the valuenext
stores the next list cell in sequenceclass ListCell:
def __init__(self,val,nxt):
self.val = val
self.next = nxt
# the list [0,1,2]
# create list cells to hold the values
l1 = ListCell(0,None)
l2 = ListCell(1,None)
l3 = ListCell(2,None)
# link them together
l1.next = l2
l2.next = l3
head = ListCell(0,ListCell(1,ListCell(2,None)))
[]
v
followed by a listclass List:
class ListCell:
def __init__(self,val,nxt):
self.val = val
self.next = nxt
def __init__(self):
self.head = None
self.len = 0
def prepend(self,val):
l = self.ListCell(val,self.head)
self.head = l
self.len += 1
i
th element we have to follow i-1
linksdef __getitem__(self,idx):
el = self.head
for i in range(1,idx):
el = el.next
return el.val
i
th cell in the listdef get_cell(self,idx):
el = self.head
for i in range(1,idx):
el = el.next
return el
get_cell
)def __delitem__(self, idx):
self.len += -1
if idx == 0:
self.head = self.head.next
else:
el = self.get_cell(idx-1)
el.next = el.next.next
delete
by using get_cell
def insert(self, idx, val):
self.len += 1
el = self.get_cell(idx)
newel = self.ListCell(val,el.next)
el.next = newel
class DoublyLinkedCell:
def __init__(self,val,nxt,prev):
self.val = val
self.nxt = nxt
self.prev = prev
head.prev
append
is now $O(1)$Operation | Array-list | Linked List |
---|---|---|
prepend | $O(n)$ | $O(1)$ |
append | $O(n)$ (amortized) | $O(1)$ (doubly-linked) |
insert | $O(n)$ | $O(n)$ |
index-access | $O(1)$ | $O(n)$ |
Operation | Array-list | Linked List |
---|---|---|
delete element | $O(n)$ | $O(n)$ |
extend | $O(n)$ | $O(1)$ (doubly-linked) |
length | $O(1)$ | $O(1)$ |