27
1 CS 103 Unit 15 Doubly-Linked Lists and Deques Mark Redekopp

CS 103 Unit 15 - USC Bitsbits.usc.edu/files/cs103/slides/Unit15_DoublyLinkedLists.pdf · List class Option 3: Circular Double-Linked List •Make first and last item point at each

  • Upload
    lamngoc

  • View
    216

  • Download
    0

Embed Size (px)

Citation preview

1

CS103Unit15

Doubly-LinkedListsandDeques

MarkRedekopp

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

10

DEQUES ANDTHEIRIMPLEMENTATION

UsingaDoubly-LinkedListtoImplementaDeque

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!

27

Activity:Writea'delist'class

• Writea'double-endedlist'classtostoreintegersthatmimicsadeque

• Supportthefollowingmethods– size()– empty()– push_back()andpop_back()– push_front()andpop_front()– back()andfront()[returnsbackorfrontinteger]