CS240
Mike Lam, Professor
CS240 Mike Lam, Professor Linked Lists Retrospective Arrays are - - PowerPoint PPT Presentation
CS240 Mike Lam, Professor Linked Lists Retrospective Arrays are great O(1) access time to any element Amortized O(1) insertion and removal Referential arrays allow arbitrary-sized objects There are still disadvantages
Mike Lam, Professor
– O(1) access time to any element – Amortized O(1) insertion and removal – Referential arrays allow arbitrary-sized objects
– Occasional O(n) worst-case costs – Requires large chunks of reserved memory – Insertion/removal in the middle is expensive
2 3 5 8
2 3 5 8 2 3 5 8
2 3 5 8 2 3 5 8 2 3 5 8
– Last item has a NULL "next" pointer
2 3 5 8
"a" "b" "c" NULL head tail single link per node
typedef struct linknode { data_t data; struct linknode *next; } linknode_t;
typedef struct { linknode_t *head; linknode_t *tail; size_t size; } linklist_t;
linknode_t* malloc_node(data_t value) {
linknode_t *new_node = (linknode_t*)malloc(sizeof(linknode_t));
// TODO: check for null new_node->value = value; new_node->next = NULL; return new_node;
}
– Solution: Track previous nodes as well
– if you have a reference to the location – O(n) if the new location is index-based or the list
– if you have a reference to the item – O(n) if you have to look for it
– Insert and remove at the head – Push, pop, and top are O(1)
– Insert at tail, remove from head
– Enqueue, dequeue, and first are O(1)
– "next" and "prev" – This is a "doubly-linked list"
– This is a "circularly-linked list"
– This is a "skip list"
– To predecessor and successor nodes
– Can now implement stacks, queues, and deques – “Deque” = “double-ended queue”
– New operation: rotate()
– No need to track both head and tail – head = tail.next
2 head tail head tail Empty list: After append(2): 2 3 head tail After append(3): 2 3 5 head tail After append(5):
void list_append(list_t *a, x) { linknode_t *new = malloc_node(x); new->prev = a->tail; new->next = NULL; if (list->head == NULL) { a->head = new; } else { a->tail->next = new; } a->tail = new; } void list_append(list_t *a, x) { linknode_t *new = malloc_node(x);
new->prev = a->tail->prev; new->next = a->tail; a->tail->prev->next = new; a->tail->prev = new; }
2 3 5 head tail head tail Empty list: Populated list:
– addfirst and removefirst – addlast and removelast
– Worst-case O(1) bounds
– O(1) insertions and removals at arbitrary positions
– O(1) access to elements by index – Proportionally fewer actual operations
– Proportionally less memory usage