CS 103 Unit 15 - USC Bitsbits.usc.edu/files/cs103/slides/Unit15_DoublyLinkedLists.pdf · List class...
Transcript of CS 103 Unit 15 - USC Bitsbits.usc.edu/files/cs103/slides/Unit15_DoublyLinkedLists.pdf · List class...
2
Singly-LinkedListReview• Usedstructures/classesand
pointerstomake‘linked’datastructures
• Singly-LinkedListsdynamicallyallocateseachitemwhentheuserdecidestoaddit.
• Eachitemincludesa'next'pointerholdingtheaddressofthefollowingItemobject
• Traversalanditerationisonlyeasilyachievedinonedirection
val next
3 0x1c0
val next
9 0x168
0x148
head
0x148 0x1c0
val next
2 0x0(Null)
0x168
#include<iostream>
using namespace std;
struct Item {int val;Item* next;
};
class List{public:List();~List();void push_back(int v); ...private:Item* head;
};
intval
Item *next
struct Item blueprint:
0x1c0
tempGiventemp…couldyoueverrecovertheaddressofthepreviousitem?
No!!!
3
Doubly-LinkedLists• Includesaprevious
pointerineachitemsothatwecantraverse/iteratebackwardsorforward
• Firstitem'spreviousfieldshouldbeNULL
• Lastitem'snextfieldshouldbeNULL
#include<iostream>
using namespace std;struct DLItem {int val;DLItem* prev;DLItem* next;
};
class DLList{public:DLList();~DLList();void push_back(int v); ...private:DLItem* head;
};
intval
DLItem *next
struct Item blueprint:DLItem *
prev
0x148
head
3 0x1c0NULL
val nextprev
9 0x2100x148
val nextprev
0x148 0x1c0
6 NULL0x1c0
val nextprev
0x210
4
Doubly-LinkedListAddFront• Addingtothefrontrequiresyoutoupdate…• …Answer
– Head– Newfront'snext&previous– Oldfront'sprevious
0x148
head
3 0x1c0NULL
val nextprev
9 0x2100x148
val nextprev
0x148 0x1c0
6 NULL0x1c0
val nextprev
0x210
12
val nextprev
0x190
5
Doubly-LinkedListAddFront• Addingtothefrontrequiresyoutoupdate…
– Head– Newfront'snext&previous– Oldfront'sprevious
0x148
head
3 0x1c00x190
val nextprev
9 0x2100x148
val nextprev
0x148 0x1c0
6 NULL0x1c0
val nextprev
0x210
12 0x148NULL
val nextprev
0x190
6
Doubly-LinkedListAddMiddle• Addingtothemiddlerequiresyoutoupdate…
– Previousitem'snextfield– Nextitem'spreviousfield– Newitem'snextfield– Newitem'spreviousfield
0x148
head
3 0x1c0NULL
val nextprev
9 0x2100x148
val nextprev
0x148 0x1c0
6 NULL0x1c0
val nextprev
0x210
12
val nextprev
0x190
7
Doubly-LinkedListAddMiddle• Addingtothemiddlerequiresyoutoupdate…
– Previousitem'snextfield– Nextitem'spreviousfield– Newitem'snextfield– Newitem'spreviousfield
0x148
head
3 0x1c0NULL
val nextprev
9 0x1900x148
val nextprev
0x148 0x1c0
6 NULL0x190
val nextprev
0x210
12 0x2100x1c0
val nextprev
0x190
8
Doubly-LinkedListRemoveMiddle
• Removingfromthemiddlerequiresyoutoupdate…– Previousitem'snextfield– Nextitem'spreviousfield– Deletetheitemobject
0x148
head
3 0x1c0NULL
val nextprev
9 0x2100x148
val nextprev
0x148 0x1c0
6 NULL0x1c0
val nextprev
0x210
9
Doubly-LinkedListRemoveMiddle
• Removingfromthemiddlerequiresyoutoupdate…– Previousitem'snextfield– Nextitem'spreviousfield– Deletetheitemobject
0x148
head
3 0x210NULL
val nextprev
9 0x2100x148
val nextprev
0x148
0x1c0
6 NULL0x148
val nextprev
0x210
11
UnderstandingPerformance• Recallvectorsaregoodatsomethingsandworseatothersintermsof
performance• TheGood:
– Fastaccessforrandomaccess(i.e.indexedaccesssuchasmyvec[6])– Allowsfor‘fast’additionorremovalofitemsattheback ofthevector
• TheBad:– Erasing/removingitematthefrontorinthemiddle(itwillhavetocopyall
itemsbehindtheremoveditemtothepreviousslot)– Addingtoomanyitems(vectorallocatesmorememorythatneededtobe
usedforadditionalpush_back()’s…butwhenyouexceedthatsizeitwillbeforcedtoallocateawholenewblockofmemoryandcopyovereveryitem
30 51 52 53 54
0 1 2 3 4 5
10
30 51 5253 54 10
30 51 5253 54 1012 18
30 51 5253 54 10 12 18
After deleting we have to move everyone up
Vector may have 1 extra slot, but when
we add 2 items a whole new block of
memory must be allocated and items
copied over
12
Deque Class
• Double-endedqueues(liketheirnamesounds)allowforefficient(fast)additionsandremovalsfromeither'end'(frontorback)ofthelist/queue
• Performance:– Slightlysloweratrandomaccess(i.e.arraystyleindexingaccesssuchas:data[3])thanvector
– Fastataddingorremovingitemsatfront orback
13
Deque Class• Similartovectorbutallowsfor
push_front()andpop_front()options
• Usefulwhenwewanttoputthingsinoneendofthelistandtakethemoutoftheother
#include <iostream>#include <deque>
using namespace std;
int main(){deque<int> my_deq; for(int i=0; i < 5; i++){my_deq.push_back(i+50);
}cout << “At index 2 is: “ << my_deq[2] ;cout << endl;
for(int i=0; i < 5; i++){int x = my_deq.front();my_deq.push_back(x+10);my_deq.pop_front();
}while( ! my_deq.empty()){cout << my_deq.front() << “ “;my_deq.pop_front();
}cout << endl;
}
my_deq 51
152 53 54 60
0 1 2 3 4
my_deq 50 51 52 53 54
0 1 2 3 4
my_deq 60 61 62 63 64
0 1 2 3 4
234
1
23
4
my_deq
after 1st iteration
after all iterations
14
Deque Implementation
• Let'sconsiderhowwecanimplementadeque• Couldweuseasingly-linkedlistandstillgetfast[i.e.O(1)]insertion/removalfrombothfrontandback?
15
List class
Singly-LinkedListDeque
• Recalladeque shouldallowforfast[i.e.O(1)]additionandremovalfromfrontorback
• Inourcurrentsingly-linkedlistweonlyknowwherethefrontisandwouldhavetotraversethelisttofindtheend(tail)
0x148
head
3 0x1c0
val next
9 0x210
val next
0x148 0x1c0
6 NULL
val next
0x210
16
List class
Option1:Singly-LinkedList+TailPointer
• Wemightthinkofaddingatailpointerdatamembertoourlistclass– Howfastcouldweaddanitemtotheend?
0x148head
0x210tail
3 0x1c0
val next
9 0x210
val next
0x148 0x1c0
6 NULL
val next
0x210
17
List class
Option1:Singly-LinkedList+TailPointer
• Wemightthinkofaddingatailpointerdatamembertoourlistclass– Howfastcouldweaddanitemtotheend?O(1)– Howfastcouldweremovethetailitem?
0x148head
0x190tail
3 0x1c0
val next
9 0x210
val next
0x148 0x1c0
6 0x190
val next
0x210
12 NULL
val next
0x190
18
List class
Option1:Singly-LinkedList+TailPointer
• Wemightthinkofaddingatailpointerdatamembertoourlistclass– Howfastcouldweaddanitemtotheend?O(1)– Howfastcouldweremovethetailitem?O(n)
• Wouldhavetowalktothe2nd tolastitem
0x148head
0x190tail
3 0x1c0
val next
9 0x210
val next
0x148 0x1c0
6 0x190
val next
0x210
12 NULL
val next
0x190
19
List class
Option2:TailPointer+Double-LinkedList
• Wemightthinkofaddingatailpointerdatamembertoourlistclass– Howfastcouldweaddanitemtotheend?
0x148head
3 0x1c0NULL
val nextprev
9 0x2100x148
val nextprev
0x148 0x1c0
6 NULL0x1c0
val nextprev
0x210
0x210tail
20
List class
Option2:TailPointer+Double-LinkedList
• Wemightthinkofaddingatailpointerdatamembertoourlistclass– Howfastcouldweaddanitemtotheend?O(1)– Howfastcouldweremovethetailitem?
0x148head
3 0x1c0NULL
val nextprev
9 0x2100x148
val nextprev
0x148 0x1c0
6 0x1900x1c0
val nextprev
0x210
0x190tail
12 NULL0x210
val nextprev
0x190
0x210
21
List class
Option2:TailPointer+Double-LinkedList
• Wemightthinkofaddingatailpointerdatamembertoourlistclass– Howfastcouldweaddanitemtotheend?O(1)– Howfastcouldweremovethetailitem?O(1)
• WeusethePREVIOUSpointertoupdatetail
0x148head
3 0x1c0NULL
val nextprev
9 0x2100x148
val nextprev
0x148 0x1c0
6 0x1900x1c0
val nextprev
0x210
0x210tail
12 NULL0x210
val nextprev
0x190
0x190
22
List class
Option2:TailPointer+Double-LinkedList
• Wemightthinkofaddingatailpointerdatamembertoourlistclass– Howfastcouldweaddanitemtotheend?O(1)– Howfastcouldweremovethetailitem?O(1)
• WeusethePREVIOUSpointertoupdatetail
0x148head
3 0x1c0NULL
val nextprev
9 0x2100x148
val nextprev
0x148 0x1c0
6 NULL0x1c0
val nextprev
0x210
0x210tail
12 NULL0x210
val nextprev
0x190
0x190
23
List class
Option3:CircularDouble-LinkedList
• Makefirstandlastitempointateachothertoformacircularlist– Weknowwhichoneisfirstviathe'head'pointer
0x148head
3 0x1c00x210
val nextprev
9 0x2100x148
val nextprev
0x148 0x1c0
6 0x1480x1c0
val nextprev
0x210
24
List class
Option3:CircularDouble-LinkedList
• Makefirstandlastitempointateachothertoformacircularlist– Weknowwhichoneisfirstviathe'head'pointer– Whatexpressionwouldyieldthetailitem?
0x148head
3 0x1c00x210
val nextprev
9 0x2100x148
val nextprev
0x148 0x1c0
6 0x1480x1c0
val nextprev
0x210
25
List class
Option3:CircularDouble-LinkedList
• Makefirstandlastitempointateachothertoformacircularlist– Weknowwhichoneisfirstviathe'head'pointer– Whatexpressionwouldyieldthetailitem?
• head->prev
0x148head
3 0x1c00x210
val nextprev
9 0x2100x148
val nextprev
0x148 0x1c0
6 0x1480x1c0
val nextprev
0x210
26
OneLastPoint
• Canthiskindofdeque implementationsupportO(1)accesstoelementi?– i.e.Canyouaccesslist[i]quicklyforanyi?
• No!!!Stillneedtotraversethelist• Youcanusea"circular"arraybaseddequeimplementationtogetfastrandomaccess– ThisissimilartowhattheactualC++deque<T>classdoes
– MoretocomeinCS104!