
Linked lists (6.5, 16) Linked lists Inserting and removing elements in the middle of a dynamic array takes O(n) time ● (though inserting at the end takes O(1) time) ● (and you can also delete from the middle in O(1) time if you don't care about preserving the order) A linked list supports inserting and deleting elements from any position in constant time ● But it takes O(n) time to access a specific position in the list Singly-linked lists A singly-linked list is made up of nodes, "here each node contains# ● some data (the node's value) ● a link (reference) to the ne$t node in the list class Node<E> { E data; Node<E> next; } Singly-linked lists %inked-list representation of the list &'(om), “Dick”, “+arry)! ',am)-# %ist itself is .ust a reference to the first node Operations on linked lists // Insert item at front of list void addFirst(E item) // Insert item after another item void addAfter(Node<E> node, E item) // Remove first item void removeFirst() // Remove item after another item void removeAfter(Node<E> node) Example list "##ist<"trin$> Node<"trin$> Node<"trin$> head ! next ! next ! data ! %Tom% data ! %Dic(% Example of addFirst(E item) Calling addFirst(“Ann”)# "##ist<"trin$> Node<"trin$> Node<"trin$> head ! next ! next ! data ! %Tom% data ! %Dic(% Node<"trin$> item.next = head; next ! head = item; data ! "Ann% item Example of addAfter Calling addAfter(tom, “Ann”)# "##ist<"trin$> Node<"trin$> Node<"trin$> head ! next ! next ! data ! %Tom% data ! %Dic(% node Node<"trin$> next = next ! datadata ! =%Ann% "Ann" item.next = node.next; itemitem node.next = item; Example of removeFirst Calling removeFirst()# "##ist<"trin$> Node<"trin$> Node<"trin$> head ! next ! next ! data ! %Tom% data ! %Dic(% node to be head = head.next; removed Example of removeAfter node to be Calling removeAfter(tom)# removed "##ist<"trin$> Node<"trin$> Node<"trin$> head ! next ! next ! data ! %Tom% data ! %Dic(% node Node<"trin$> next ! data ! "Ann% node.next = node.next.next; A problem It's bad A0I design to need both addFirst and addAfter (like"ise removeFirst and removeAfter): ● (wice as much code to "rite 1 twice as many places to introduce bugs! ● Users of the list library will need special cases in their code for dealing with the first node Idea# add a header node! a fake node that sits at the front of the list but doesn't contain any data Instead of addFirst(x)! we can do addAfter(headerNode, x) List with header node (16" .1) If "e "ant to add 'Ann” before '(om), we can do addAfter(head, “Ann”) "##ist<"trin$> Node<"trin$> Node<"trin$> Node<"trin$> head ! next ! next ! next ! null data = data ! %Tom% data ! %Dic(% 4e header node! #o$bly-linked lists In a singly-linked list you can only go forwards through the list# ● If you're at a node, and want to find the previous node, too bad2 Only way is to search forward from the beginning of the list In a doubly-linked list! each node has a link to the ne$t and the previous nodes 5ou can in O(1) time# ● go forwards and backwards through the list ● insert a node before or after the current one ● modify or delete the current node 4e “classic) data structure for se6uential access A do$bly-linked list 4e list itself 7ach node links to links to the first the ne$t and the and last nodes previous node %nsertion and deletion in do$bly- linked lists Similar to singly-linked lists, but you have to update the prev pointer too8 (o delete the current node the idea is# node.next.-rev ! node+-rev; node.-rev.next ! node+next; Node<String> Node<"trin$> Node<"trin$> next ! next ! next = prev = -rev ! prev = data = )&om” data ! "'ic(% data = %Ann% %nsertion and deletion in do$bly- linked lists, 'ontinued (o delete the current node the idea is# node+next+-rev ! node+-rev; node+-rev+next ! node+next; But this CRA,+7, if we try to delete the first node! since then node+-rev !! n,ll! Also! if "e delete the first node! we need to update the list object's head8 %ots and lots of special cases for all operations# ● :hat if the node is the first node; ● :hat if the node is the last node; ● :hat if the list only has one element so the node is both the first and the last node; (etting rid of the special 'ases +ow can "e get rid of these special cases? One idea (see book): use a header node like for singly linked lists, but also a footer node8 ● head and tail will point at the header and footer node ● <o data node will have n,ll as its next or -rev ● All special cases gone! ● Small problem: allocates two extra nodes per list A cute solution: circularly-linked list with header node )ir'$larly-linked list with header node #inked#ist <"trin$> Node<"trin$> head ! next ! -rev ! data ! %Tom% Node<String> Node<"trin$> next ! next ! prev ! -rev ! data ! data ! %Dic(% Node<"trin$> +ere is the next ! header node prev ! ('prev” links data ! ".arry% not sho"n) )ir'$larly-linked list with header node :orks out quite nicely! ● head.next is the first element in the list ● head.-rev is the last element ● you never need to update head ● no node's next or -rev is ever n,ll ● so no special cases2 5ou can even make do "ithout the header node – then you have one special case! "hen you need to update head Stacks and lists $sing linked lists 5ou can implement a stack using a linked list# ● push# add to front of list ● pop: remove from front of list 5ou can also implement a queue: ● en6ueue# add to rear of list ● de6ueue# remove from front of list A *$eue as a singly-linked list :e can implement a queue as a singly linked list with an e$tra rear pointer# :e en6ueue elements by adding them to the back of the list# ● ,et rear.next to the ne" node ● 3pdate rear so it points to the ne" node Linked lists vs dynamic arrays *ynamic arrays# ● have O(1) random access (get and set) ● have amortised O(1) insertion at end ● have O(n) insertion and deletion in middle %inked lists# ● have O(n) random access ● have O(1) se6uential access ● have O(1) insertion in an arbitrary place (but you have to find that place first) /omplement each other! +hat's the problem with this- int s,m(Lin(ed#ist<Integer> list) { int total = 0; for (int i = 0; i < list+si1e(); i2+) total 2! list+$et(i); ret,rn total; } list8get is O(n) – so the whole thing is O(n=)! .etter! int s,m(Lin(ed#ist<Integer> list) { int total = 0; for (int i: list) total 2! i; ret,rn total; } Remember – linked lists are for sequential access only Linked lists 0 summary 0rovide sequential access to a list ● ,ingly-linked 1 can only go for"ards ● *oubly linked 1 can go for"ards or back"ards Many variations 1 header nodes! circular lists – but they all implement the same abstract data type (interface) Can insert or delete or modify a node in O(1) time But unlike arrays, random access is O(n) ?ava: LinkedList<E> class Hash tables (19.1 – 19.3, 19.5 – 19.6) 1ash tables naïvely A hash table implements a set or map 4e plan# take an array of si@e k *efine a hash function that maps values to indices in the range {B!888!k-1C ● 7$ample# if the values are integers! hash function might be h(n) = n mod k (o find, insert or remove a value x, put it in index h(x) of the array Hash tables naïvely, example Implementing a set of integers, suppose "e take a hash table of si@e D and a hash function h(n) = n mod 5 B 1 = F E This hash table contains 3 4 5 AD! G! 17} Similarly! if we Inserting 1E gives# "anted to find G! B 1 = F E "e would look it 3 4 5 14 up in inde$ 3 A problem 4is naIve idea doesn't "ork8 :hat if "e "ant to insert 1= into the set; B 1 = F E 3 4 5 :e should store 1= at index 2! but there's already something there! 4is is called a collision 6he problem with naïve hash tables <aIve hash tables have t"o problems# 1. Sometimes t"o values have the same hash – this is called a collision ● ("o "ays of avoiding collisions! chaining and probing – "e "ill see them later =. The hash function is specific to a particular si@e of array ● Allo" the hash function to return an arbitrary integer and then take it modulo the array size# h(x) = x.hashCode() mod array.si!e Avoiding 'ollisions: chaining Instead of an array of elements, have an array of linked lists (o add an element, calculate its hash and insert it into the list at that inde$ B 1 = F E 3 4 5 Avoiding 'ollisions: chaining Instead of an array of elements, have an array of linked lists (o add an element, calculate its hash and insert it into the list at that inde$ B 1 = F E Inserting 1= into the table 3 4 5 8 9erforman'e of chained hash tables If the linked lists are small! chained hash tables are fast ● If the size is bounded! operations are O(1) time But if they get big! everything gets slo" Observation 1: the array must be big enough ● If the hash table gets too full (a high load factor)! allocate a ne" array of about t"ice the si@e (rehashing) Observation =# the hash function must evenly distribute the elements! ● If everything has the same hash code! all operations are O(n) #efining a good hash fun'tion :hat is wrong "ith the following hash function on strings; "dd together the character code of each character in the string (character code of a J KH! b = KG! c = 99 etc8) >aps e8g.
Details
-
File Typepdf
-
Upload Time-
-
Content LanguagesEnglish
-
Upload UserAnonymous/Not logged-in
-
File Pages61 Page
-
File Size-