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

linked lists last today next interfaces implementing
SMART_READER_LITE
LIVE PREVIEW

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


slide-1
SLIDE 1

Linked Lists

slide-2
SLIDE 2

LAST Interfaces

  • Stacks
  • Queues

TODAY Implementing stacks and queues Linked lists NEXT Better arrays

slide-3
SLIDE 3

How to implement queues

  • Data structure with a flexible size
  • Recursive structure
  • Base case: empty list
  • Recursive case: something followed by a list
slide-4
SLIDE 4

Linked list implementation (for integers)

What if there was no pointer here?

struct list_node { int data; struct list_node* next; };

slide-5
SLIDE 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

slide-6
SLIDE 6

Linked list implementation (for integers)

typedef struct list_node list; struct list_node { int data; list* next; };

slide-7
SLIDE 7

Class activity

There is an embedded linked list in the class!

slide-8
SLIDE 8

Fixed element type

typedef struct list_node list; struct list_node { int data; list* next; };

slide-9
SLIDE 9

Linked list implementation (general)

typedef string elem; // This goes in the client's code

How should we indicate the end of a linked list?

typedef struct list_node list; struct list_node { elem data; list* next; };

slide-10
SLIDE 10

List segments [start, end)

typedef struct list_node list; struct list_node { elem data; list* next; }; bool is_segment(list* start, list* end)

slide-11
SLIDE 11

List segments [start, end)

bool is_segment(list* start, list* end) { if (start == NULL) return false; if (start == end) return true; return is_segment(start->next, end); }

recursive implementation

typedef struct list_node list; struct list_node { elem data; list* next; };

slide-12
SLIDE 12

List segments [start, end)

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

iterative implementation

slide-13
SLIDE 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?

slide-14
SLIDE 14

Tortoise and hare

bool is_acyclic(list* start);

tortoise hare

slide-15
SLIDE 15

Adding and removing elements

slide-16
SLIDE 16

Delete (remove) from the start of a list segment

Cost: O(1)

Consider a non-empty list segment [start, end)

elem x = start->data; start = start->next; return x;

slide-17
SLIDE 17

Delete (remove) from the end of a list segment

Cost: O(n)

Consider a non-empty list segment [start, end) 3 4 5

before

3 4

after

start end

slide-18
SLIDE 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)

slide-19
SLIDE 19

Insertion at the end of a list segment

Cost: O(1)

set end to it

end start

3 4 5

start end new node

3 4 5 6

set the data field of end to the value to add

3 4 5 6

set its next field to a new dummy node

slide-20
SLIDE 20

Insertion at the end of a list segment (code)

end->data = x; list* new_dummy = alloc(list); end->next = new_dummy; end = new_dummy;

Cost: O(1)

Consider a list segment [start, end)

slide-21
SLIDE 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
slide-22
SLIDE 22

Insertion at the end of a list segment

3 4 5 3 4 5

start end

6

new node

Consider the alternative sequence of steps to add 6

Cost: O(n)

slide-23
SLIDE 23

Implementing Queues with Linked Lists

slide-24
SLIDE 24

Queue implementation

// 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); @*/ ;

Interface Implementation Code using linked lists

slide-25
SLIDE 25
  • Enqueue from back
  • Dequeue from front

struct queue_header { list* front; list* back; };

header {

slide-26
SLIDE 26

Considering cost of insert and delete for linked lists what should be front and back?

// 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); @*/ ;

slide-27
SLIDE 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

slide-28
SLIDE 28

Queue implementation

// 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); @*/ ;

Interface Implementation

struct queue_header { list* front; list* back; }; typedef struct queue_header queue; typedef queue* queue_t; … queue_t queue_new() //@ensures is_queue(\result); //@ensures queue_empty(\result); …

slide-29
SLIDE 29

Representation invariant

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

Q

slide-30
SLIDE 30

Detecting emptiness

bool queue_empty(queue* Q) //@requires is_queue(Q); { }

Cost: O(1)

return Q->front == Q->back; struct queue_header { list* front; list* back; }; typedef struct queue_header queue; typedef queue* queue_t;

// 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); @*/ ;

Interface

slide-31
SLIDE 31

Creating a new queue

queue* queue_new() //@ensures is_queue(\result); //@ensures queue_empty(\result); { }

// 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); @*/ ;

Interface

Cost: O(1)

queue* Q = alloc(queue); list* l = alloc(list); Q->front = l; Q->back = l; return Q; struct queue_header { list* front; list* back; }; typedef struct queue_header queue; typedef queue* queue_t;

slide-32
SLIDE 32

Implementing stacks with Linked Lists

slide-33
SLIDE 33

Implementing stacks as list segments

  • Insert and remove from the beginning

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

slide-34
SLIDE 34

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

slide-35
SLIDE 35

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

slide-36
SLIDE 36

Linked Lists versus Arrays

UNSORTED ARRAYS LINKED LISTS PROS

  • O(1) access
  • built in support
  • self-resizing
  • O(1) insertion (given

right pointers)

  • O(1) deletion (given

right pointers) CONS

  • Fixed size
  • O(n) insertion
  • No built-in support
  • O(n) access