740 likes | 867 Views
Chapter #4: LISTS. Pointers. array - sequential representation - some operation can be very time- consuming (data movement) - size of data must be predefined - static storage allocation and deallocation solution to the data movement in sequential representation
E N D
Chapter #4: LISTS
Pointers • array • - sequential representation • - some operation can be very time- • consuming (data movement) • - size of data must be predefined • - static storage allocation and • deallocation • solution to the data movement in sequential representation • - pointers: often called links
Pointers • for any type T in C • - there is corresponding type • pointer-to-T • actual value of pointer type • - an address of memory • pointer operators in C • - the address operator: & • - the dereferencing(or indirection) • operator: *
Pointers • dynamically allocated storage • - C provides a mechanism, called a • heap, for allocating storage at • run-time • int i,*pi; • float f,*pf; • pi = (int *)malloc(sizeof(int)); • pf = (float *)malloc(sizeof(float)); • *pi = 1024; • *pf = 3.14; • printf(“an integer=%d,a float=%f\n”,*pi,*pf); • free(pi); • free(pf);
ptr bat cat sat vat NULL Singly Linked Lists • - compose of data part and link part • - link part contains address of the • next element in a list • - non-sequential representations • - size of the list is not predefined • - dynamic storage allocation and • deallocation
ptr bat cat sat vat NULL mat Singly Linked Lists • to insert the word mat between cat and sat • 1)get a node currently unused(paddr) • 2)set the data of this node to mat • 3)set paddr’s link to point to the • address found in the link of the • node cat • 4)set the link of the node cat to • point to paddr
ptr bat cat mat sat vat NULL Singly Linked Lists • to delete mat from the list • 1)find the element that immediately • precedes mat, which is cat • 2)set its link to point to mat’s • link • - no data movement in insert and • delete operation
Singly Linked Lists • required capabilities to make linked representations possible • - a mechanism for defining a node’s • structure, that is, the field it • contains • - a way to create new nodes when we • need them • - a way to remove nodes that we no • longer need
Singly Linked Lists • Ex 4.1 [list of words ending in at] • define a node structure for the list • - data field: character array • - link field: pointer to the next • node • - self-referential structure • typedef struct List_Node { • char data[4]; • struct List_Node *link; • } list_node; • typedef struct list_node *list_ptr; • list_ptr ptr = NULL;
b a t \0 Singly Linked Lists • create new nodes for out list • then place the word bat into our list • ptr=(list_ptr)malloc(sizeof(list_node)); • strcpy(ptr->data,”bat”); • ptr->link=NULL; address of first node ptr->data ptr->link NULL ptr
10 Singly Linked Lists • Ex 4.2 [two-node linked list] • create a linked list of integers • #include <stdio.h> • struct List_Node { • int data; • struct List_Node *link; • }; • typedef struct List_Node list_node; • typedef struct List_Node *list_ptr; • main() • { • list_node first = { 10, NULL}; • list_ptr ptr = &first; • } ptr first.data first.link NULL ptr->data ptr->link
10 20 NULL Singly Linked Lists • main() • { • list_node first = { 10, NULL}; • list_ptr ptr = &first; • list_node second = { 20, NULL}; • first.link = &second; • } ptr first second
10 10 20 20 NULL NULL 50 Singly Linked Lists • Ex 4.3 [list insertion] • determine if we have used all available memory: IS_FULL ptr ptr node temp
Singly Linked Lists • main() • { • list_node first = { 10, NULL}; • list_ptr ptr = &first; • list_node second = { 20, NULL}; • first.link = &second; • insert(&first) • } • void insert(list_ptr node) { • list_ptr temp; • temp=(list_ptr)malloc(sizeof(list_node)); • if(IS_FULL(temp)) { • fprintf(stderr,”The momory is full\n”); • exit(1); • } • temp->data=50; • temp->link = node->link; • node->link = temp; • }
Singly Linked Lists • Ex 4.4 [list deletion] • deletion depends on the location of the node: more complicated • assumption • - ptr: point to the start of list • - node: point to the node to be • deleted • - trail: point to the node that • precedes node to be deleted
ptr node trail = NULL ptr 10 50 20 50 20 NULL NULL (a) before deletion (b) after deletion 10 50 20 10 20 NULL NULL Singly Linked Lists • 1) the node to be deleted is the • first node in the list • 2) otherwise ptr trail node ptr (a) before deletion (b) after deletion
Singly Linked Lists • main() • { • list_node first = { 10, NULL}; • list_ptr ptr = &first; • list_node second = { 20, NULL}; • first.link = &second; • insert(&first) • delete(&ptr, &first, first.link); • } • void delete(list_ptr *pptr, list_ptr trail, • list_ptr node) • { • if(trail) • trail->link = node->link; • else • *pptr = (*pptr)->link; • free(node); • }
Singly Linked Lists • Ex 4.5 [printing out a list] • while not end of the list do • print out data field; • move to the next node; • end; • void print_list(list_ptr ptr) { • printf(“The list contains: “); • for(; ptr; ptr = ptr->link) • printf(“%4d”, ptr->data); • printf(“\n”); • }
top element link ······ NULL front rear element link ······ NULL Dynamically Linked stacks And Queues • representing stack / queue by linked list (a) linked stack (b) linked queue
Dynamically Linked Stacks And Queues • representing n stacks by linked lists • #define MAX_STACKS 10 /* n=MAX_STACKS=10 */ • typedef struct { • int key; • /* other fields */ • } element; • struct Stack { • element item; • struct Stack *link; • }; • typedef struct Stack stack; • typedef struct Stack *stack_ptr; • stack_ptr top[MAX_STACKS];
top[0] element link key ······ NULL top[1] ······ NULL top[MAX_STACKS-1] ······ NULL Dynamically Linked Stacks And Queues · · ·
Dynamically Linked stacks And Queues • initial condition for stacks • top[i] = NULL, 0 £ i < MAX_STAKCS • boundary condition for n stacks • - empty condition: • top[i] = NULL iff the ith stack is empty • - full condition: • IS_FULL(temp) iff the memory is full
Dynamically Linked Stacks And Queues • add to a linked stack • … • push( &top[stack_no], item_x); • … • void push(stack_ptr *ptop, element item) { • stack_ptr temp = • (stack_ptr)malloc(sizeof (stack)); • if(IS_FULL(temp)) { • fprintf(stderr,”The memory is full\n”); • exit(1); • } • temp->item=item; • temp->link=*ptop; • *ptop = temp; • }
Dynamically Linked Stacks And Queues • delete from a linked stack • … • item_x = pop(&top[stack_no]); • … • element pop(stack_ptr *ptop) { • stack_ptr temp = *ptop; • element item; • if(IS_EMPTY(temp)) { • fprintf(stderr,”The stack is empty\n”); • exit(1); • } • item=temp->item; • *ptop=temp->link; • free(temp); • return item; • }
Dynamically Linked Stacks And Queues • representing m queues by linked lists • #define MAX_QUEUES 10 /* m=MAX_QUEUES=10 */ • struct queue { • element item; • struct queue *link; • }; • typedef struct queue *queue_ptr; • queue_ptr front[MAX_QUEUES],rear[MAX_QUEUES];
front[0] rear[0] element link key ······ NULL front[1] rear[1] ······ NULL front[MAX_QUEUES-1] rear[MAX_QUEUES-1] ······ NULL Dynamically Linked Stacks And Queues · · ·
Dynamically Linked Stacks And Queues • initial conditon for queues • front[i]=NULL,0 £i < MAX_QUEUES • boundary condition for queues • - empty condition: • front[i]= NULL iff the ith queue is empty • - full condition: • IS_FULL(temp) iff the memory is full
Dynamically LinkedStacks And Queues • add to the rear of a linked queue • void insert(queue_ptr *pfront, • queue_ptr *prear, element item) { • queue_ptr temp = • (queue_ptr)malloc(sizeof(queue)); • if(IS_FULL(temp)) { • fprintf(stderr,”The memory is full\n”); • exit(1); • } • temp->item=item; • temp->link=NULL; • if (*pfront) • (*prear)->link=temp; • else • *pfront = temp; • *prear = temp; • }
Dynamically Linked Stacks And Queues • delete from the front of a linked queue • element delete(queue_ptr *pfront) { • queue_ptr temp=*pfront; • element item; • if (IS_EMPTY(*front)) { • fprintf(stderr,”The queue is empty\n”); • exit(1); • } • item=temp->item; • *pfront=temp->link; • free(temp); • return item; • }
Dynamically Linked Stacks And Queues • representing stacks/queues by linked • lists • - no data movement is necessary : • O(1) • - no full condition check is • necessary • - size is growing and shrinking • dynamically
Polynomials • representing polynomials as singly linked lists • A(x) = am-1xem-1 + ··· + a0xe0 • typedef struct poly_node *poly_ptr; • typedef struct poly_node { • int coef; • int expon; • poly_ptr link; • }; • poly_ptr a,b,d;
coef expon link a 3 14 2 8 1 0 NULL b 8 14 -3 10 10 6 NULL Polynomials • poly_node • a = 3x14 + 2x8 + 1 • b = 8x14 - 3x10 + 10x6
3 14 2 8 1 0 NULL a 8 14 -3 10 10 6 NULL b 11 14 NULL d rear Polynomials • adding polynomials • (a) a->expon == b->expon
3 14 2 8 1 0 NULL a 8 14 -3 10 10 6 NULL b 11 14 -3 10 NULL d rear Polynomials • (b) a->expon < b->expon
3 14 2 8 1 0 NULL a 8 14 -3 10 10 6 NULL b 11 14 -3 10 2 8 NULL d rear Polynomials • (c) a->expon > b->expon
3 14 2 8 1 0 NULL a 8 14 -3 10 10 6 NULL b 11 14 -3 10 2 8 d 10 6 NULL rear Polynomials • (d) a->expon < b->expon
3 14 2 8 1 0 NULL a 8 14 -3 10 10 6 NULL b 11 14 -3 10 2 8 d 10 6 1 0 NULL rear Polynomials • (e) b == NULL;
Polynomials • poly_ptr padd(poly_ptr a,poly_ptr b) { • poly_ptr front,rear,temp; • int sum; • rear=(poly_ptr)malloc(sizeof(poly_node)); • if(IS_FULL(rear)) { • fprintf(stderr,”The memory is full\n”); • exit(1); • } • front = rear; • (to be continued)
Polynomials • while(a && b) • switch(COMPARE(a->expon,b->expon)) { • case -1: /* a->expon < b->expon */ • attach(b->coef,b->expon,&rear); • b = b->link; • break; • case 0: /* a->expon = b->expon */ • sum = a->coef + b->coef; • if(sum) attach(sum,a->expon,&rear); • a = a->link; b = b->link; break; • case 1: /* a->expon > b->expon */ • attach(a->coef,a->expon,&rear); • a = a->link; • } • (to be continued)
Polynomials • for(; a; a=a->link) • attach(a->coef,a->expon,&rear); • for(; b; b=b->link) • attach(b->coef,b->expon,&rear); • rear->link = NULL; • temp=front; front=front->link; free(temp); • return front; • }
Polynomials • function attach() to create a new node and append it to the end of d • void attach(float coe,int exp,poly_ptr *pptr) • { • poly_ptr temp; • temp=(poly_ptr)malloc(sizeof(poly_node)); • if(IS_FULL(temp)) { • fprintf(stderr,”The memory is full\n”); • exit(1); • } • temp->coef = coe; • temp->expon = exp; • (*pptr)->link = temp; • *pptr=temp; • }
Polynomials • analysis of padd where • m, n : number of terms in each • polynomial • - coefficient additions: • O(min{m, n}) • - exponent comparisons: • O(m + n) • - creation of new nodes for d • O(m + n) • time complexity: • O(m + n)
Polynomials • erasing polynomials • e(x) = a(x) * b(x) + d(x) • poly_ptr a, b, d, e; • ··· • a = read_poly(); • b = read_poly(); • d = read_poly(); • temp = pmult(a, b); • e = padd(temp, d); • print_poly(e);
Polynomials • void erase(poly_ptr *pptr) { • poly_ptr temp; • while (*pptr) { • temp = *pptr; • *pptr = (*pptr)->link; • free(temp); • } • } • useful to reclaim the nodes that are being used to represent partial result such as temp(x)
NULL Polynomials • allocating/deallocating nodes • how to preserve free node in a storage pool ? • - initially link together all free nodes into a list in a storage pool • - avail: variable of type poly_ptr that points to the first node in list of freed nodes storage pool 1 2 n avail ······ initial available space list
Polynomials • Allocating nodes • poly_ptr get_node(void) { • poly_ptr node; • if (avail) { • node = avail; avail = avail->link; • } • else { • node = • (poly_ptr)malloc(sizeof(poly_node)); • if (IS_FULL(node)) { • fprintf(stderr,”The memory is full\n”); • exit(1); • } • } • return node; • }
Polynomials • Deallocating nodes • void ret_node(poly_ptr ptr) { • ptr->link = avail; • avail = ptr; • }
Polynomials • void erase(poly_ptr *pptr) { • poly_ptr temp; • while (*pptr) { • temp = *pptr; • *pptr = (*pptr)->link; • ret_node(temp); • } • } - traverse to the last node in the list: • O(n) where n: number of term - how to erase polynomial efficiently? how to return n used nodes to storage pool ?
Polynomials • representing polynomials as circularly linked list • to free all the nodes of a polynomials more efficiently • - modify list structure • the link of the last node points to the first node in the list • - called circular list (« chain) ptr
Polynomials • maintain our own list (as a chain) • of nodes that has been freed • - obtain effective erase algorithm • void cerase(poly_ptr *pptr) { • if (*pptr) { • temp = (*pptr)->link; • (*pptr)->link = avail; • avail = temp; • *pptr = NULL; • } • } • independent of the number of nodes • in a list: O(1)