Programming Data Structures and Algorithms Linked List Stacks

  • Slides: 33
Download presentation
Programming, Data Structures and Algorithms (Linked List, Stacks and Queues) Anton Biasizzo Programming, Data

Programming, Data Structures and Algorithms (Linked List, Stacks and Queues) Anton Biasizzo Programming, Data Structures and Algorithms (Lists, stacks, and queues) Slide 1/33

Abstract Data Types (ADT) q q The basic rule of programming: short routines Break

Abstract Data Types (ADT) q q The basic rule of programming: short routines Break the program into modules: logical unit for specific job Module size is kept small by spliting into sub-modules Advantages of modularity: § Easier to debug § Several programmers can work on same program § Easier program modifications and updates q An Abstract Data Type (ADT) is a data type with the given set of operations. q Mathematical abstraction – implementation not specified q Example: set ADT, operations: union, intersection, size, complement, … Programming, Data Structures and Algorithms (Lists, stacks, and queues) Slide 2/33

Lists q q q General list of form A 1, A 2, A 3,

Lists q q q General list of form A 1, A 2, A 3, …, AN. Size of list is N; if N=0 it is null list Ai+1 follows (succeeds) Ai (i<N), Ai-1 precedes Ai (i>1) The elements in lists are of arbitrary complex data type Associated operations on lists: § § § § Size, Find, Index, Insert, Delete, Next, Previous, Print. List, … Programming, Data Structures and Algorithms (Lists, stacks, and queues) Slide 3/33

Array implementation q Straight forward approach q Array size: § For static array size

Array implementation q Straight forward approach q Array size: § For static array size is pre-declared at compile time § For dynamically allocated array its size is determined at allocation time § Estimation on maximum list size leads to high over-estimation q Index operations require constant time (O(1)). q Print. List and Find operations are carried out in linear time (O(n)). q Insertion and Deletion are expensive (O(n)). q Rarely used for list implementation Programming, Data Structures and Algorithms (Lists, stacks, and queues) Slide 4/33

Linked List q Insertion and deletion in contiguous (array) implementation requires moving part of

Linked List q Insertion and deletion in contiguous (array) implementation requires moving part of list. q Linked list consist of a series of records, not necessarily adjacent in memory. q Record contains the element and a pointer to a following record. q The field of the record referenced by a pointer p can be accessed by p->field_name or (*p). field_name Programming, Data Structures and Algorithms (Lists, stacks, and queues) Slide 5/33

Linked List Operations q Print. List and Find operations: § § Pass a pointer

Linked List Operations q Print. List and Find operations: § § Pass a pointer to first element of the list as a starting point. Traverse the list by following the next pointers. for (p=L; p!=NULL; p=p->next) { print_record(p) } § § Linear time operations (O(n)). Slightly slower then in the array implementation. q Index operation is not as efficient as in the array impl. : § Index(p, i) takes O(i) time; traversing from the start Programming, Data Structures and Algorithms (Lists, stacks, and queues) Slide 6/33

Insertion and deletion q Insertion operation requires: § § Allocation of new element (malloc,

Insertion and deletion q Insertion operation requires: § § Allocation of new element (malloc, new) Two pointer maneuver q Deletion operation requires: § § One pointer change Deallocation of deleted element Programming, Data Structures and Algorithms (Lists, stacks, and queues) Slide 7/33

Programming details q Problems with described implementation: § Insertion in the front of the

Programming details q Problems with described implementation: § Insertion in the front of the list § Deleting from the front of the list is a special case § Keep track of deleted cells q Sentinel node at the beginning (header or dummy node) q Type declaration: typedef struct node *node_ptr; struct node { element_type element; node_ptr next; }; typedef node_ptr LIST; typedef node_ptr position; Programming, Data Structures and Algorithms (Lists, stacks, and queues) Slide 8/33

Programming details q Function to test if list is empty int is_empty( LIST L)

Programming details q Function to test if list is empty int is_empty( LIST L) { return (L->next == NULL); } q Function to test if current position is the last in the linked list int is_last(position p) { return (p->next == NULL); } q Find function position find(element_type x, LIST L) { position p; p = L->next; while ( (p != NULL) && (p->element != x) ) return p; } Programming, Data Structures and Algorithms (Lists, stacks, and queues) p = p->next; Slide 9/33

Programming details q Function for deletion of element § Delete only first occurrence of

Programming details q Function for deletion of element § Delete only first occurrence of element § Do nothing if element is not in the list § Use function find_previous, similar to find function void delete( element_type x, LIST L) { position p, tmp_cell; p = find_previous(x, L); if (p->next != NULL) { // implicit assumption of header use tmp_cell = p->next; p->next = tmp_cell->next; // bypass the cell to be deleted free( tmp_cell ); } } q Function find_previous finds the predecessor of the cell with element Position find_previous( element_type x, LIST L ) { position p; p = L; while ( (p->next != NULL) && (p->next->element != x) ) return p; } Programming, Data Structures and Algorithms (Lists, stacks, and queues) p = p->next; Slide 10/33

Programming details q Function for insertion of element after position void insert( element_type x,

Programming details q Function for insertion of element after position void insert( element_type x, LIST L, position p) { position tmp_cell; tmp_cell = (position) malloc(sizeof(struct node) ); if ( tmp_cell == NULL) fatal_error(“Out of space!!!”); else { tmp_cell->element = x; tmp_cell->next = p->next; p->next = tmp_cell; } } q With exception find and find_previous, all operations take O(1) time. q In the worst case the running time of find and find_previous is O(n). q In average case the running time of find and find_previous is O(n) (half of the list must be traversed). Programming, Data Structures and Algorithms (Lists, stacks, and queues) Slide 11/33

Doubly Linked Lists q Sometimes it is convenient to traverse lists backwards. q The

Doubly Linked Lists q Sometimes it is convenient to traverse lists backwards. q The standard implementation (using find_previous) is awkward. q Add an extra field to the structure that points to previous record. q Increase space requirement q Double insertion and deletion cost Programming, Data Structures and Algorithms (Lists, stacks, and queues) Slide 12/33

Circularly Linked Lists q q Last cell keeps a pointer to the first. Header

Circularly Linked Lists q q Last cell keeps a pointer to the first. Header cell is redundant. Can also be implemented with doubly linked lists. Tests in functions (e. g. is_last(), find(), …) must be modified. Programming, Data Structures and Algorithms (Lists, stacks, and queues) Slide 13/33

Example: polynomial q Define ADT for single-variable polynomials by using lists q If most

Example: polynomial q Define ADT for single-variable polynomials by using lists q If most of the coefficient ai are nonzero, we use a simple array. q Define operations: § § Initialize polynomial to zero, Addition, Subtraction, Multiplication, … q Type declaration typedef struct { int coeff[MAX_DEGREE+1]; unsigned int high_power; } *POLYNOMIAL; Programming, Data Structures and Algorithms (Lists, stacks, and queues) Slide 14/33

Example: polynomial q Procedure to initialize polynomial to zero: void zero_polynomial( POLYNOMIAL poly )

Example: polynomial q Procedure to initialize polynomial to zero: void zero_polynomial( POLYNOMIAL poly ) { unsigned int i; for (i=0; i<=MAX_DEGREE; i++) poly->high_power = 0; poly->coeff[i] = 0; } q Procedure to add two polynomial: void add_polynomial( POLYNOMIAL poly 1, POLYNOMIAL poly 2, POLYNOMIAL sum ) { unsigned int i; zero_polynomial( sum ); sum->high_power = max ( poly 1 ->high_power, poly 2 ->high_power); for (i=0; i<=sum->high_power; i++) sum->coeff[i] = poly 1 ->coeff[i] + poly 2 ->coeff[i]; } Programming, Data Structures and Algorithms (Lists, stacks, and queues) Slide 15/33

Example: polynomial q Procedure to multiply two polynomial: void mult_polynomial( POLYNOMIAL poly 1, POLYNOMIAL

Example: polynomial q Procedure to multiply two polynomial: void mult_polynomial( POLYNOMIAL poly 1, POLYNOMIAL poly 2, POLYNOMIAL prod ) { unsigned int i, j; zero_polynomial( prod ); prod->high_power = poly 1 ->high_power + poly 2 ->high_power; if ( prod->high_power > MAX_DEGREE ) error(“Exceeds size”); else { for (i=0; i<=poly 1 ->high_power; i++) for (j=0; j<=poly 2 ->high_power; j++) prod->coeff[i+j] += poly 1 ->coeff[i] * poly 2 ->coeff[j]; } } q Running time for multiplication is proportional to the product of the degree of two input polynomials (O(n 2)) Programming, Data Structures and Algorithms (Lists, stacks, and queues) Slide 16/33

Example: sparse polynomial q In the sparse polynomial most coefficients are zero. q For

Example: sparse polynomial q In the sparse polynomial most coefficients are zero. q For sparse polynomial array implementation is unacceptable: § § Large memory space overhead Large addition and especially multiplication operation time q Type declaration: typedef struct node *node_ptr; struct node { int coefficient; int exponent; node_ptr next; } ; Programming, Data Structures and Algorithms (Lists, stacks, and queues) Slide 17/33

The Stack ADT q q q Stack is a list with restrictions One end

The Stack ADT q q q Stack is a list with restrictions One end of the list (typically beginning) is called “top” Insertions and deletions performed only on top Stack also called LIFO (last in first out) Stack ADT operations: § § § § Push operation: insert operation on top Pop operation: delete most recently inserted element (delete from top) Top operation: examine most recently inserted element Operation to empty stack Operation to check the emptiness of stack Pop or Top operation on empty stack is ADT error Running out of space on Push operation is implementation error Programming, Data Structures and Algorithms (Lists, stacks, and queues) Slide 18/33

Linked List Implementation of Stack q Linked List Implementation: § § Push inserts at

Linked List Implementation of Stack q Linked List Implementation: § § Push inserts at the beginning of the list Pop deletes from the beginning of the list Top examines the element at the front of the list Implement stack using a header q Type declaration: typedef struct node *node_ptr; struct node { element_type element; node_ptr next; }; typedef node_ptr STACK; /* Stack implementation use a header/sentinel node */ Programming, Data Structures and Algorithms (Lists, stacks, and queues) Slide 19/33

Linked List Implementation of Stack q Function to test if list is empty int

Linked List Implementation of Stack q Function to test if list is empty int is_empty( STACK S) { return (S->next == NULL); } q Functions to create empty stack STACK create_stack(void) { S = (STACK) malloc( sizeof( struct node) ); if (S == NULL) fatal_error(“Out of space!!!”); return (S); } void make_null( STACK S ) { if ( S != NULL ) S->next = NULL; else error(“Must use create_stack first”); } Programming, Data Structures and Algorithms (Lists, stacks, and queues) Slide 20/33

Linked List Implementation of Stack q Push operation void push(element_type x, STACK S) {

Linked List Implementation of Stack q Push operation void push(element_type x, STACK S) { node_ptr tmp_cell; tmp_cell = (node_ptr) malloc( sizeof( struct node ) ); if (tmp_cell == NULL) fatal_error(“Out of space!!!”); else { tmp_cell->element = x; tmp_cell->next = S->next; S->next = tmp_cell; } } q Top operation element_type top(STACK S) { if ( is_empty( S ) ) error(“Empty stack”); else return S->next->element; } Programming, Data Structures and Algorithms (Lists, stacks, and queues) Slide 21/33

Linked List Implementation of Stack q Pop operation void pop(STACK S) { node_ptr first_cell;

Linked List Implementation of Stack q Pop operation void pop(STACK S) { node_ptr first_cell; if ( is_empty( S ) ) error( “Empty stack”); else { first_cell = S->next; S->next = S->next; free( first_cell ); } } q All operations take constant time: § § No reference to the size No loops q Drawback: calls to malloc and free are expensive Programming, Data Structures and Algorithms (Lists, stacks, and queues) Slide 22/33

Array Implementation of Stack q Array Implementation: § § § Avoids pointers, array size

Array Implementation of Stack q Array Implementation: § § § Avoids pointers, array size defined in advance The number of elements does not gets too large Top of stack is designated by current index tos (end of the list) q Type declaration: struct stack_record { unsigned int stack_size; int top_of_stack; element_type *stack_array; }; typedef struct stack_record *STACK; #define EMPTY_TOS (-1) /* Signifies an empty stack */ Programming, Data Structures and Algorithms (Lists, stacks, and queues) Slide 23/33

Array Implementation of Stack q Stack creation STACK create_stack(unsigned int max_elements) { STACK S;

Array Implementation of Stack q Stack creation STACK create_stack(unsigned int max_elements) { STACK S; S = (STACK) malloc( sizeof( struct stack_record) ); if (S == NULL) fatal_error(“Out of space!!!”); S->stack_array = (element_type *) malloc( sizeof( element_type ) * max_elements ); if( S->stack_array == NULL ) fatal_error( “Out of space!!!”); S->top_of_stack = EMPTY_TOS; S->stack_size = max_elements; return (S); } q Freeing stack structure void dispose_stack(STACK S) { if ( S != NULL ) { free( S->stack_array ); free( S ); } } Programming, Data Structures and Algorithms (Lists, stacks, and queues) Slide 24/33

Array Implementation of Stack q Function to test if list is empty int is_empty(

Array Implementation of Stack q Function to test if list is empty int is_empty( STACK S) { return (S->top_of_stack == EMPTY_TOS); } q Functions to create empty stack void make_null( STACK S ) { if ( S != NULL ) S->top_of_stack = EMPTY_TOS; else error(“Must use create_stack first”); } q Push operation void push(element_type x, STACK S) { if ( is_full( S ) ) error(“Full stack”); else S->stack_array[ ++S->top_of_stack ] = x; } Programming, Data Structures and Algorithms (Lists, stacks, and queues) Slide 25/33

Array Implementation of Stack q Top operation element_type top(STACK S) { if ( is_empty(

Array Implementation of Stack q Top operation element_type top(STACK S) { if ( is_empty( S ) ) error(“Empty stack”); else return S->stack_array[ S->top_of_stack ]; } q Pop operation void pop(STACK S) { if ( is_empty( S ) ) error( “Empty stack”); else S->top_of_stack--; } q All operations take very small constant time: § § Integer push and pop operations in single machine instruction After array most fundamental data type q Error testing affects efficiency § Skip error checking unless error handling is crucial (OS) Programming, Data Structures and Algorithms (Lists, stacks, and queues) Slide 26/33

Stack applications q Balancing symbols § A tool to parse source code and check

Stack applications q Balancing symbols § A tool to parse source code and check if everything is balanced (braces, brackets, parenthesis, etc) § The sequence [()] is legal but [(]) is wrong Create empty stack Read symbols until end-of-file if symbol is “open anything” push it to stack if it is “close” then if stack is empty report an error else pop the stack if popped symbol does not correspond to symbol read report an error if stack is not empty report an error Programming, Data Structures and Algorithms (Lists, stacks, and queues) Slide 27/33

Arithmetic postfix expressions q Calculate the expression 3. 99 * 1. 06 + 4.

Arithmetic postfix expressions q Calculate the expression 3. 99 * 1. 06 + 4. 99 + 5. 99 * 1. 1 = q Result depends on used calculator (scientific or simple fourfunction) q Postfix or reverse Polish notation: operations are specified after the operands 3. 99 1. 06 * 4. 99 + 5. 99 1. 1 * + q Easy to implement using stack q Programming language Postscript uses postfix notation Programming, Data Structures and Algorithms (Lists, stacks, and queues) Slide 28/33

Infix to postfix conversion q Stack can be used for conversion from standard form

Infix to postfix conversion q Stack can be used for conversion from standard form into postfix q Operands are immediately placed on the output q Operators and left parenthesis are placed onto the stack q If right parenthesis is read, we pop the stack, writing the symbols until we encounter a left parenthesis, which is popped but not placed on the output. q If operator symbols is read, then we pop entries from stack until we find entry of lower priority, when popping is done the operator is pushed on stack. q If we read the end of input, we pop the stack until it is empty and place symbols on the output Programming, Data Structures and Algorithms (Lists, stacks, and queues) Slide 29/33

Function calls q Local variables of the function residing in the processor registers must

Function calls q Local variables of the function residing in the processor registers must be saved when calling new function. q The current location in the routine must be saved, so that the processor knows where to resume the execution once the called function returns. q Using stack enable the recursion q Saved information is called activation record or stack frame. q Analogy function call and function return with open and close parenthesis in the problem of balancing symbols. Programming, Data Structures and Algorithms (Lists, stacks, and queues) Slide 30/33

The Queue ADT q Queues are lists with restrictions q Insertions are done at

The Queue ADT q Queues are lists with restrictions q Insertions are done at one end while deletions are performed on other end q Queues are also called FIFO (first in first out) q Queue ADT operations: § § Enqueue operation: insert element at the end of the list Dequeue operation: delete element from the start of the list Programming, Data Structures and Algorithms (Lists, stacks, and queues) Slide 31/33

Queues implementations q Any list implementation can be used for queue implementation q Linked

Queues implementations q Any list implementation can be used for queue implementation q Linked list and array implementations give fast O(1) running times q Data structure of an array implementation of queues § § Array QUEUE[] Position (index) q_front Position (index) q_rear Number of elements in the queue q_size q Enqueue element x: § § Increment q_size and q_rear Set QUEUE[q_rear] = x q Dequeue element: § § § Set return value to QUEUE[q_frone] Increment q_front Decrement q_size q Whenever q_front or q_rear reach the end of the array, they are wrapped around to the beginning of the array (circular buffer) Programming, Data Structures and Algorithms (Lists, stacks, and queues) Slide 32/33

Queues applications q Printing § When print job is submitted to a printer, they

Queues applications q Printing § When print job is submitted to a printer, they are arranged in the order of arrival q Managing the email system q Events in windowing environments (MS Windows, X Windows, …) q Buffer implementation in various device drivers § § § Network driver Serial line driver Disk access q Event driven simulations q Wherever the resources are limited queues are employed Programming, Data Structures and Algorithms (Lists, stacks, and queues) Slide 33/33