1 / 145

List, (dynamic) linked list

Let’s first forget about ‘classes’, but only a dynamic list. We make lists with ‘classes’ afterwards. List, (dynamic) linked list. A simple list Example: using a dynamic array. concept of a list, e.g. a list of integers Print out info Empty test Search an element

mindy
Télécharger la présentation

List, (dynamic) linked list

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Let’s first forget about ‘classes’, but only a dynamic list. We make lists with ‘classes’ afterwards. List, (dynamic) linked list

  2. A simple list Example: using a dynamic array • concept of a list, e.g. a list of integers • Print out info • Empty test • Search an element • Insertion (at head, at end, any position) • Deletion • … • implemented • by a static array (over-sized if necessary) int list[1000]; int size; • by a dynamic array int list[size]; int size; • by a linked list and more …

  3. How to use a list? int main() { cout << "Enter list size: "; int n; cin >> n; int* A = new int[n]; initialize(A, n, 0); print(A, n); A = addEnd(A,n,5); print(A, n); A = addHead(A,n,5); print(A, n); A = deleteFirst(A,n); print(A, n); selectionSort(A, n); print(A, n); delete [] A; } int A[10000]; int n; Nothing compulsory in programming, only style matters!

  4. Initialize void initialize(int list[], int size, int value){ for(int i=0; i<size; i++) list[i] = value; }

  5. Print out a list void print(int list[], int size) { cout << "[ "; for(int i=0; i<size; i++) cout << list[i] << " "; cout << "]" << endl; }

  6. Delete the first element // for deleting the first element of the array int* deleteFirst(int list[], int& size){ int* newList; newList = new int[size-1]; // make new array if(size){ // copy and delete old array for(int i=0; i<size-1; i++) newList[i] = list[i+1]; delete [] list; } size--; return newList; }

  7. Remark: Instead of A = deleteFirst(A,n) we can also just deleteFirst(A,n) if we define as a void type function: void deleteFirst(int*& A, int& size) { … A = newList; } We can also B = deleteFirst(A,n) if we keep the original intact

  8. Adding Elements // for adding a new element to end of array int* addEnd(int list[], int& size, int value){ int* newList; newList = new int [size+1]; // make new array if(size){ // copy and delete old array for(int i=0; i<size; i++) newList[i] = list[i]; delete [] list; } newList[size] = value; size++; return newList; }

  9. Add at the beginning: // for adding a new element at the beginning of the array int* addHead(int list[], int& size, int value){ int* newList; newList = new int [size+1]; // make new array if(size){ // copy and delete old array for(int i=0; i<size; i++) newList[i+1] = list[i]; delete [] list; } newList[0] = value; size++; return newList; }

  10. Linked list: a dynamic list

  11. Motivation • list using static array int myArray[1000]; int n; We have to decide (to oversize) in advance the size of the array (list) • list using dynamic array int* myArray; int n; cin >> n; myArray = new int[n]; We allocate an array (list) of any specified size while the program is running • linked-list (dynamic size) size = ?? The list is dynamic. It can grow and shrink to any size.

  12. Link Data 20 45 75 85 Array naturally represents a (ordered) list, the link is implicit, consecutive and contiguous! Now the link is explicit, any places! Data 75 85 20 45 1 array 0 2 Link Link Data 45 linked list 85 20 75

  13. Link Data 20 45 75 85 Linked Lists: Basic Idea • A linked list is an ordered collection of data • Each element of the linked list has • Some data • A link to the next element • The link is used to chain the data Example: A linked list of integers:

  14. 20 45 addEnd(75), addEnd(85) 20 45 75 85 deleteEnd(85), deleteHead(20), deleteHead(45) Linked Lists: Basic Ideas • The list can grow and shrink 75

  15. Linked Lists: Operations • Original linked list of integers: • Insertion (in the middle): • Deletion (in the middle) 20 45 75 85 old value 20 45 75 85 60 20 45 75 85 deleted item

  16. Definition of linked list type: struct Node{ int data; Node* next; }; We can also: typedef Node* NodePtr;

  17. Linked List Structure • Node : Data + Link • Definition struct Node { int data; //contains useful information Node* next; //points to next element or NULL }; • Create a Node Node* p; p = new Node; //points to newly allocated memory • Delete a Node delete p;

  18. Access fields in a node (*p).data; //access the data field (*p).next; //access the pointer field Or it can be accessed this way p->data //access the data field p->next //access the pointer field

  19. Head 20 45 75 85 Representing and accessing linked lists • We define a pointer Node* head; that points to the first node of the linked list. When the linked list is empty then head is NULL.

  20. Passing a Linked List to a Function It is roughly the same as for an array!!! • When passing a linked list to a function it should suffice to pass the value of head. Using the value of head the function can access the entire list. • Problem: If a function changes the beginning of a list by inserting or deleting a node, then head will no longer point to the beginning of the list. • Solution: When passing head always pass it by reference (not good!) or using a function to return a new pointer value

  21. Implementation of an (Unsorted) Linked List

  22. Head 20 newPtr Start the first node from scratch head = NULL; Node* newPtr; newPtr = new Node; newPtr->data = 20; newPtr->next = NULL; head = newPtr; Head

  23. Inserting a Node at the Beginning newPtr = new Node; newPtr->data = 13; newPtr->next = Head; head = newPtr; 20 Head 13 newPtr

  24. Head 50 40 13 20 newPtr Keep going …

  25. Adding an element to the head: NodePtr& void addHead(Node*& head, int newdata){ Node* newPtr = new Node; newPtr->data = newdata; newPtr->next = Head; head = newPtr; } Call by reference, scaring!!!

  26. Also written (more functionally) as: Node* addHead(Node* head, int newdata){ Node* newPtr = new Node; newPtr->data = newdata; newPtr->next = Head; return newPtr; } Compare it with ‘addHead’ with a dynamic array implementation

  27. Deleting the Head Node Node* p; p = head; head = head->next; delete p; head (to delete) 50 40 13 20 p

  28. void deleteHead(Node*& head){ if(head != NULL){ NodePtr p = head; head = head->next; delete p; } } As a function: Node* deleteHead(Node* head){ if(head != NULL){ NodePtr p = head; head = head->next; delete p; } return head; }

  29. Displaying a Linked List p = head; p = p->next; head 20 45 p head 20 45 p

  30. A linked list is displayed by walking through its nodes one by one, and displaying their data fields (similar to an array!). void displayList(Node* head){ NodePtr p; p = head; while(p != NULL){ cout << p->data << endl; p = p->next; } } For an array: void displayArray(int data[], int size) { int n=0; while ( n<size ) { cout << data[i] << endl; n++; } }

  31. Searching for a node (look at array searching first!) //return the pointer of the node that has data=item //return NULL if item does not exist Node* searchNode(Node* head, int item){ NodePtr p = head; NodePtr result = NULL; bool found=false; while((p != NULL) && (!found)){ if(p->data == item) { found = true; result = p;} p = p->next; } return result; }

  32. Remember array searching algorithm: void main() { const int size=8; int data[size] = { 10, 7, 9, 1, 17, 30, 5, 6 }; int value; cout << "Enter search element: "; cin >> value; int n=0; int position=-1; bool found=false; while ( (n<size) && (!found) ) { if(data[n] == value) { found=true; position=n;} n++; } if(position==-1) cout << "Not found!!\n"; else cout << "Found at: " << position << endl; } It is essentially the same!

  33. Variations of linked lists • Unsorted linked lists • Sorted linked lists • Circular linked lists • Doubly linked lists • …

  34. Further considerations for the unsorted lists: • Physical copy of list for operators like ‘deleteHead’ and ‘addHead’ • ‘deleteHead’ should be understood as a decomposition into a sub-list …

  35. B = deleteHead(A); Node* deleteHead(Node* head){ // physically copy head into a new one, newhead // so to keep the original list intact! Node* newhead=NULL; Node* temp=head; while(temp!=NULL) { newhead=addEnd(newhead,temp->data); temp=temp->next; } if(newhead != NULL){ Node* p = newhead; newhead = newhead->next; delete p; } return newhead; }

  36. 50 40 13 20 More operation: adding to the end • Original linked list of integers: • Add to the end (insert at the end): 60 50 40 13 20 Last element The key is how to locate the last element or node of the list!

  37. Add to the end: void addEnd(NodePtr& head, int newdata){ NodePtr newPtr = new Node; newPtr->data = newdata; newPtr->next = NULL; NodePtr last = head; if(last != NULL){ // general non-empty list case while(last->next != NULL) last=last->next; last->next = newPtr; } else // deal with the case of empty list head = newPtr; } Link new object to last->next Link a new object to empty list

  38. Add to the end as a function: NodePtr addEnd(NodePtr head, int newdata){ NodePtr newPtr = new Node; newPtr->data = newdata; newPtr->next = NULL; NodePtr last = head; if(last != NULL){ // general non-empty list case while(last->next != NULL) last=last->next; last->next = newPtr; } else // deal with the case of empty list head = newPtr; return head; }

  39. Implementation of a Sorted Linked List

  40. Head ... 20 45 75 prev cur 33 newPtr Inserting a Node 1. (a) Create a new node using: NodePtr newPtr = new node; (b) Fill in the data field correctly. 2. Find “prev” and “cur” such that the new node should be inserted between *prev and *cur. 3. Connect the new node to the list by using: (a) newPtr->next = cur; (b) prev->next = newPtr;

  41. Finding prev and cur Suppose that we want to insert or delete a node with data value newValue. Then the following code successfully finds prev and cur such that prev->data < newValue <= cur->data

  42. It’s a kind of search algo, prev = NULL; cur = head; found=false; while( (cur!=NULL) && (!found) ) { if (newValue > cur->data) { prev=cur; cur=cur->next; } else found = true; } Prev is necessary as we can’t go back!

  43. Finally, it is equivalent to: prev = NULL; cur = head; while( (cur!=NULL) && (newValue>cur->data) ) { prev=cur; cur=cur->next; } Logical AND (&&) is short-circuited, sequential, i.e. if the first part is false, the second part will not be executed.

  44. //insert item into linked list according to ascending order Node* insertNode(Node* head, int item){ NodePtr newp, cur, pre; newp = new Node; newp->data = item; pre = NULL; cur = head; while( (cur != NULL) && (item>cur->data)){ pre = cur; cur = cur->next; } if(pre == NULL){ //insert to head of linked list newp->next = head; head = newp; } else { pre->next = newp; new->next = cur; } return head; } If the position happens to be the head General case

  45. // not recommended void type function void insertNode(NodePtr& head, int item){ NodePtr newp, cur, pre; newp = new Node; newp->data = item; pre = NULL; cur = head; while( (cur != NULL) && (item>cur->data)){ pre = cur; cur = cur->next; } if(pre == NULL){ //insert to head of linked list newp->next = head; head = newp; } else { pre->next = newp; new->next = cur; } }

  46. Deleting a Node • To delete a node from the list 1. Locate the node to be deleted (a) cur points to the node. (b) prev points to its predecessor 2. Disconnect node from list using: prev->next = cur->next; 3. Return deleted node to system: delete cur; (to delete) Head ... 20 45 75 85 prev cur

  47. Delete an element in a sorted linked list: Get the location Node* deleteNode(Node* head, int item){ NodePtr prev=NULL, cur = head; while( (cur!=NULL) && (item > cur->data)){ prev = cur; cur = cur->next; } if ( cur!==NULL && cur->data==item) { if(cur==head) head = head->next; else prev->next = cur->next; delete cur; } return head; } We can delete only if the element is present! If (cur==NULL || cur->data!=item) Item is not in the list! If the element is at the head General case

  48. // in a void function, not recommended Get the location void deleteNode(NodePtr& head, int item){ NodePtr prev=NULL, cur = head; while( (cur!=NULL) && (item > cur->data)){ prev = cur; cur = cur->next; } if ( cur!==NULL && cur->data==item) { if(cur==Head) Head = Head->next; else prev->next = cur->next; delete cur; } } We can delete only if the element is present! If (cur==NULL || cur->data!=item) Item is not in the list! If the element is at the head General case

  49. Example of a (dynamic) class: linked list class

  50. linked lists: definition struct Node{ int data; Node* next; }; typedef Node* NodePtr; NodePtr head; bool listEmpty(NodePtr head) { } int getHead(NodePtr head) { } NodePtr getRest(NodePtr head) { } NodePtr addHead(NodePtr head, int newdata) { } void delHead(NodePtr& Head){ }

More Related