linked lists last today next interfaces implementing
play

Linked Lists LAST TODAY NEXT Interfaces Implementing stacks and - PowerPoint PPT Presentation

Linked Lists LAST TODAY NEXT Interfaces Implementing stacks and queues Better arrays Stacks Linked lists Queues How to implement queues Data structure with a flexible size Recursive structure Base case: empty list


  1. Linked Lists

  2. LAST TODAY NEXT Interfaces Implementing stacks and queues Better arrays • Stacks Linked lists • Queues

  3. How to implement queues • Data structure with a flexible size • Recursive structure • Base case: empty list • Recursive case: something followed by a list

  4. Linked list implementation (for integers) struct list_node { int data; struct list_node* next; }; What if there was no pointer here?

  5. Linked list implementation (for integers) struct list_node { int data; struct list_node* next; }; Let us introduce a shorter name for this structure type

  6. Linked list implementation (for integers) typedef struct list_node list; struct list_node { int data; list* next; };

  7. Class activity There is an embedded linked list in the class!

  8. Fixed element type typedef struct list_node list; struct list_node { int data; list* next; };

  9. Linked list implementation (general) typedef string elem; // This goes in the client's code typedef struct list_node list; struct list_node { elem data; list* next; }; How should we indicate the end of a linked list?

  10. typedef struct list_node list; List segments [start, end) struct list_node { elem data; list* next; }; bool is_segment(list* start, list* end)

  11. typedef struct list_node list; List segments [start, end) struct list_node { elem data; list* next; }; bool is_segment(list* start, list* end) { if (start == NULL) return false; recursive if (start == end) return true; implementation return is_segment(start->next, end); }

  12. typedef struct list_node list; List segments [start, end) struct list_node { elem data; list* next; }; bool is_segment(list* start, list* end){ for (list* p = start; p != NULL; p = p->next) { iterative if (p == end) return true; implementation } return false; }

  13. Observations about is_segment • Always returns true when [start, end) is a valid segment • Does it always return false when it is [start, end) is not a valid segment? • Only if start is NULL-terminated • Loops forever if it contains a cycle How can we detect a cycle?

  14. Tortoise and hare bool is_acyclic(list* start); tortoise hare

  15. Adding and removing elements

  16. Delete (remove) from the start of a list segment Consider a non-empty list segment [start, end) elem x = start->data; start = start->next; return x; Cost: O(1)

  17. Delete (remove) from the end of a list segment Consider a non-empty list segment [start, end) start end 3 4 5 before 3 4 after Cost: O(n)

  18. Insertion at the start of a list segment Consider a list segment [start, end) list* l = alloc(list); l->data = x; l->next = start; start = l; Cost: O(1)

  19. Insertion at the end of a list segment start end 3 4 5 set the data field of end 3 4 5 6 to the value to add new node set its next field to 3 4 5 6 a new dummy node end set end to it start Cost: O(1)

  20. Insertion at the end of a list segment (code) Consider a list segment [start, end) end->data = x; list* new_dummy = alloc(list); end->next = new_dummy; end = new_dummy; Cost: O(1)

  21. Insertion at the end of a list segment Consider the alternative sequence of steps • create a new node • set its data field to the value to add • set its next field to end • point the old last node to it •

  22. Insertion at the end of a list segment Consider the alternative sequence of steps to add 6 start end 3 4 5 3 4 5 new node 6 Cost: O(n)

  23. Implementing Queues with Linked Lists

  24. Queue implementation Interface Implementation // typedef ______* queue_t; bool queue_empty(queue_t Q) /* O(1) */ /*@requires Q != NULL; @*/; Code using linked lists queue_t queue_new() /* O(1) */ /*@ensures \result != NULL; @*/ /*@ensures queue_empty(\result); @*/; void enq(queue_t Q, string e) /* O(1) */ /*@requires Q != NULL; @*/; string deq(queue_t Q) /* O(1) */ /*@requires Q != NULL; @*/ /*@requires !queue_empty(Q); @*/ ;

  25. • Enqueue from back • Dequeue from front header { struct queue_header { list* front; list* back; };

  26. // typedef ______* queue_t; bool queue_empty(queue_t Q) /* O(1) */ /*@requires Q != NULL; @*/; queue_t queue_new() /* O(1) */ /*@ensures \result != NULL; @*/ /*@ensures queue_empty(\result); @*/; void enq(queue_t Q, string e) /* O(1) */ /*@requires Q != NULL; @*/; string deq(queue_t Q) /* O(1) */ /*@requires Q != NULL; @*/ /*@requires !queue_empty(Q); @*/ ; Considering cost of insert and delete for linked lists what should be front and back?

  27. Implementing queues as list segments • Insert at the back and remove from front [start, end) of a list segment becomes [front, back) of a queue

  28. Queue implementation Interface Implementation struct queue_header { // typedef ______* queue_t; list* front; list* back; bool queue_empty(queue_t Q) /* O(1) */ }; /*@requires Q != NULL; @*/; typedef struct queue_header queue; queue_t queue_new() /* O(1) */ /*@ensures \result != NULL; @*/ typedef queue* queue_t; /*@ensures queue_empty(\result); @*/; … void enq(queue_t Q, string e) /* O(1) */ queue_t queue_new() /*@requires Q != NULL; @*/; // @ensures is_queue(\result); //@ensures queue_empty(\result); string deq(queue_t Q) /* O(1) */ /*@requires Q != NULL; @*/ … /*@requires !queue_empty(Q); @*/ ;

  29. Representation invariant Q bool is_segment(list* start, list* end); bool is_queue(queue* Q) { return Q != NULL && is_acyclic … && is_segment … }

  30. Detecting emptiness Interface struct queue_header { list* front; list* back; }; // typedef ______* queue_t; typedef struct queue_header queue; bool queue_empty(queue_t Q) /* O(1) */ /*@requires Q != NULL; @*/; typedef queue* queue_t; queue_t queue_new() /* O(1) */ /*@ensures \result != NULL; @*/ /*@ensures queue_empty(\result); @*/; bool queue_empty(queue* Q) void enq(queue_t Q, string e) /* O(1) */ //@requires is_queue(Q); /*@requires Q != NULL; @*/; { return Q->front == Q->back; string deq(queue_t Q) /* O(1) */ /*@requires Q != NULL; @*/ } /*@requires !queue_empty(Q); @*/ ; Cost: O(1)

  31. Creating a new queue Interface struct queue_header { list* front; list* back; }; // typedef ______* queue_t; typedef struct queue_header queue; bool queue_empty(queue_t Q) /* O(1) */ typedef queue* queue_t; /*@requires Q != NULL; @*/; queue_t queue_new() /* O(1) */ /*@ensures \result != NULL; @*/ /*@ensures queue_empty(\result); @*/; queue* queue_new() //@ensures is_queue(\result); void enq(queue_t Q, string e) /* O(1) */ //@ensures queue_empty(\result); /*@requires Q != NULL; @*/; { string deq(queue_t Q) /* O(1) */ queue* Q = alloc(queue); /*@requires Q != NULL; @*/ list* l = alloc(list); /*@requires !queue_empty(Q); @*/ ; Q->front = l; Q->back = l; return Q; Cost: O(1) }

  32. Implementing stacks with Linked Lists

  33. Implementing stacks as list segments • Insert and remove from the beginning [start, end) of a list segment becomes [top, floor) of a stack

  34. [start, end) of a list segment becomes [top, floor) of a stack

  35. typedef struct stack_header stack; struct stack_header { list* top; list* floor; };

  36. Linked Lists versus Arrays UNSORTED ARRAYS LINKED LISTS • self-resizing • O(1) insertion (given • O(1) access PROS right pointers) • built in support • O(1) deletion (given right pointers) • Fixed size • No built-in support CONS • O(n) insertion • O(n) access

Recommend


More recommend