cs 32: discussion

56
CS 32: Discussion Winter2019 - Section 3C Youfu Li [email protected] Credit: Carey Nachenberg, Muhao Chen

Upload: khangminh22

Post on 20-Apr-2023

8 views

Category:

Documents


0 download

TRANSCRIPT

CS 32: DiscussionWinter2019 - Section 3C

Youfu [email protected]

Credit: CareyNachenberg,Muhao Chen

Outline

• LinkedLists• DoublyLinkedList• SortedLinkedList• ReverseaLinkedList

LinkedLists

LinkedLists

• Akeycomponentofalinkedlistisanode,whichisasingleunitofdata.

• Thefirstboxcarriesavalue,andthesecondisapointer toanothernode• HereisanexamplenodedefinitionintheformofaC++struct:Typedef int ItemType;Struct Node{

ItemType value;Node *next;

};

value *next

LinkedLists

• Linkedlistisaseriesofnodes,eachpointingtothenextone.

• Thelastnode’snextpointerisNULL.

• Whatistheinformationyouneedtocompletethepicture?

HeadPointer!

• Obviously,youneedtoknowwhereitbegins.

• Wekeepapointerthatpointstothefirstitemandcallitthehead

pointer.

• e.g.Node *head;

LinkedLists(Min.Requirements)

• Youneedadescription ofanode,whichmustcontainanextpointer.

• Youneedahead pointerthatpointstothefirstnode.

• Thelistmustbeloop-free(unlessitisacircularlylinedlist,inwhich

caseone(andonlyone)loopmustexist).

LinkedLists(Insertion)

• Addinganewvaluetothelist.

LinkedLists(Insertion)

1.Createanewnode.Callthepointertoitp.

LinkedLists(Insertion)

2.Makeitsnext pointerpointtothefirstitem.p->next = head;

LinkedLists(Insertion)

3.Maketheheadpointerpointtothenewnode.head = p;

LinkedLists(Insertion)

• Whataboutinsertioninthemiddleofthelist?• Attheendofthelist?

End(q):q->next=p;p->next=NULL;Middle(afterq):p->next=q->next;q->next=p;

LinkedLists(Search)

Node* Search(int key, Node* head){ Node *q = head;while(q != NULL) {

if(q -> value != key) q = q -> next; //move to next

else return q;

} return NULL; }

LinkedLists(Removal)

• Supposethereisanitemthatyouwanttoremove,anditispointedbyapointer,sayp.

• CanIjustdo“deletep;”?

• Weneedtosetthepreviousnode’s(q)next pointertopointtothenextnodeofp !

LinkedLists(Removal)

• Whenlookingupp,keepthepointertothepreviousnode(q).

• Then…q->next = p->next;delete p;

LinkedLists(Removal)

• SanityChecks• Doesitworkifp==head?• Doesitworkifp pointstothelastone?

q->next = p->next;Delete p;

LinkedLists(Removal)

• Ifp==head,thereisno”previous”nodetop.• Makeanexceptionforthis.

• Weneedtoresettheheadpointer.

head = p->next;Delete p;

LinkedLists(Removal-- Summary)void remove(int valToRemove, Node* head) {

Node *p = head, *q = NULL; while (p != NULL) {

if (p->value == valToRemove) break;

q = p; //q keeps track the previous of p p = p->next;}

if (p == NULL) return;

if (p == head) //node to remove is head head = p->next;

elseq->next = p->next;

delete p; }

What’sniceaboutlinkedlists

• Veryefficientinsertion• Flexiblememoryallocation

• Thinkaboutwhatyoushoulddoifyouhavetogrow/shrinkadynamicallyallocatedarray.

• Andyes,thereisalittleoverhead,butthat’sthepricewepay.

• Simpletoimplement

What’snotsoniceaboutlinkedlists

• Slowsearch(i.e.accessingacertainelement,e.g.”getthe

4237th item”)

• Usually,searchistheoperationthatmattersmorethaninsertion

orremoval.

Variations

• SortedLinkedLists• Makechangestotheinsertionmethod.

• DoublyLinkedLists• Eachnodehasprev andnext pointers.• Atail pointeriskepttopointtothelastnode.• Whydoyouthinkthisisuseful?

• CircularlyLinkedLists• Thelastnode’snextpointerpointstothefirstone.• Essentially,thereisno”first”node.

AClassicProblemaboutCircularlyLinkedList

• Givenaheadnodeofalinkedlist,howtoverifywhetherthereisaloopinthelinkedlistornot?

DoublyLinkedList

DoublyLinkedList

• Alinkedlistwhereeachnodehastwopointers:• Next– pointingtothenextnode• Prev – pointingtothepreviousnode

struct Node { int value; Node *Next; Node *Prev;

};

DoublyLinedList

• That’showitlookslike:

• FeaturestocaptureaDLL:• Twopointers:head,tail• head->prev =NULL• tail->next=NULL• head==tail==NULLwhenlistisempty

Insertion

FourdifferentconditionstoinsertanewnodeP• 1.Insertbeforethehead;• 2.Insertafterthetail;• 3.Insertsomewhereinthemiddle;• 4.Whenlistisempty;

Insertion(Beforehead)

• 1)Settheprev ofheadtothenewnodep• head->prev =p;

• 2)Setthenext ofp tohead• p->next=head;

• 3)p becomesthenewhead• head=p;

• 4)head->prev =NULL;

Insertion(Aftertail)

• Quitethesameasinsertionbeforehead:

tail->next=p;p->prev =tail;tail=p;p->next=NULL;

Insertioninthemiddle(afternodeq)

• 1)Fixthenextnodeofq first:• Node*r=q->next;

• 2)Pointbothnext ofq andprev ofr top• q->next=r->prev =p;

• 3)Pointbothsidesofp toq andr respectively:• p->prev =q;• p->next=r;

Insertioninthemiddle(afternodeq)

• Ordoitwithoutr:

• p->prev =q;

• p->next=q->next;

• q->next=q->next->prev =p;

Insertion(toanemptylist)

• Howdowerepresentanemptylist?

• head==NULL(Ortail==NULL;Orhead==tail==NULL)

• 1)Insertion,justsetp ashead aswellastail:

• head=tail=p;

• 2)Don’tforgettosetNULLonbothsides:

• p->next=p->prev =NULL;

Search

• Justlikethesinglylinkedlist.

Node* Search(int key, Node* head){

Node *q = head;

while(q != NULL) {

if(q -> value == key) return q;

else q = q -> next; //iterate to the next node

}

return NULL;

}

Node* Search(int key, Node* tail){

Node *q = tail;

while(q != NULL) {

if(q -> value == key) return q;

else q = q -> prev; //iterate to the previous node

}

return NULL;

}

Removal

• Morecomplexthansinglylinkedlist.

• Checkifthenodep isthehead(p==head).Letthisboolean beA.

• Checkifthenodeisthetail(p==tail).Letthisboolean beB.

Removal

Fourcases:• Case1(A,butnotB):P istheheadofthelist,andthereismorethanonenode.

• Case2(B,butnotA):P isthetailofthelist,andthereismorethanonenode.

• Case3(AandB):P istheonlynode.• Case4(notAandnotB):P isinthemiddleofthelist.

RemovalCase1(P ishead)

• 1)Updatehead• head=head->next;

• 2)deletep• deletep;

• 3)Settheprev ofhead toNULL• head->prev =NULL;

RemovalCase2(P istail)

• 1)Updatetail

• tail=tail->prev;

• 2)deletep

• 3)Setthenext oftail toNULL

• tail->next=NULL;

RemovalCase3(P istheonlynode)

• 1)Emptythelinkedlist:• head=tail=NULL;

• 2)deletep

RemovalCase4(P isinthemiddle)

• 1)Fixtheprev andnextofp:• Node*q=p->prev;• Node*r=p->next;

• 2)Concatenateq andr:• q->next=r;• r->prev =q;

• 3)Deletep

RemovalCase4(Equivalentimplementation)

• Ifwedonotfixwithq andr:• p->prev ->next=p->next;• p->next->prev =p->prev;• deletep;

RemovalSummaryvoidremoveNodeInDLL(Node*p,Node&*head,Node&*tail){if(p==head&&p==tail)//case3head=tail=NULL;

elseif(p==head){//case1head=head->next;head->prev =NULL;

}elseif(p==tail){//case2tail=tail->prev;tail->next=NULL;

}else{//case4p->prev ->next=p->next;p->next->prev =p->prev;

}deletep;

}

Copyingadoublylinkedlist

• 1)Createheadandtail forthenewlist• 2)Iteratethroughtheoldlist.Foreachnode,copyitsvaluetoanewnode.

• 3)Insertthenewnodetothetailofthenewlist.• 4)Repeat3untilwehaveiteratedtheentireoldlist.SetNULLbeforehead andnextoftail.

CopyaDoublyLinkedList

Cautionsaboutcodingwithalinkedlist

• Todrawdiagramsofnodeswillbeextremelyhelpful.• Whencopyingalinkedlist,onlycopyvaluestonewnodes.Donotcopypointers.

SortedLinkedList

Doweneedtosearchtheentirelinked?

• Consideranascendingsorted(doublylinked)list:

• Doweneedtosearchthroughallthenodeswhenwe’researchingfor:

• 8• 50

• Awaytooptimizethesearch:sortedlistandearlystop

Howtoimplementanascendingsorted(doublylinked)list?• Changetheinsertion.Findthenodeq whosevalueisthegreatestlowerbound tothenewnodep.

• 1)Checkifhead’s valueislargerthanp’s.Ifso,insertp ashead.if (p -> value < head -> value) {

p -> next = head; head -> prev = p; p -> prev = NULL; head = p;

}

Howtoimplementanascendingsorted(doublylinked)list?• 2)ifnot,iteratethroughthelistuntilwefindthenodeq whosevalueisthegreatestlowerboundtop.

• Note:q->nextcaneitherhaveavaluelargerthanq,orisNULL.

Node *q = head -> next;while (q && q -> value < p -> value) {

if (q-> next == NULL || q -> next -> value > p -> value) break; q = q -> next;

}

Howtoimplementanascendingsorted(doublylinked)list?• 3)Insert pafterq:if(q->next!=NULL)q->next->prev =p;

p->next=q->next;/*ifqisthelastnodethenitsnextisalreadyNULL*/p->prev =q;q->next=p;

Insertintoanascendingdoublylinkedlistvoidinsert(Node*p,Node*head){if(p->value<head->value){p->next=head;head->prev =p;p->prev =NULL;head=p;return;

}Node*q=head->next;while(q->value<p->value){if(q->next==NULL||q->next->value>p->value)break;q=q->next;

}if(q->next!=NULL)q->next->prev =p;

p->next=q->next;p->prev =q;q->next=p;

}

Earlystopinsearchingasortedlinkedlist

• Westoptheiterationonceweseeanodewhichstoresavaluethatislargerthankey.

Node* Search(int key, Node* head){ Node *q = head;while(q != NULL && q -> value <= key) {

if(q -> value == key) return q; else q = q -> next; //iterate to the next node

} return NULL;

}

Whataboutremovalandupdate?

Whyearlystoptechniquesavescost

• Sparecostfromsearchtoinsertionandupdate• However,searchiscalledmassively,butinsertionandupdatenot.• O(n/2)costissavedforeachsearch(assumedatacomplieswithauniformdistribution)

ReverseaLinkedList

ReverseLinkedList(Leetcode #206,easy)

Givenasinglylinkedlist,reverseeverynodeofit(i.e.eachnextpointstothepreviousnode).

Node*reverseList(Node*head)

Solution

Node* reverseList(struct ListNode* head) { Node *prev=NULL,*cur=head,*next; while(cur) {

next = cur->next; cur->next = prev; prev = cur;cur = next;

} return prev;

}

Questions?Practice, practice, practice