array ◦ sequential representation ◦ some operation can be very time-consuming (data movement)...

Post on 04-Jan-2016

221 Views

Category:

Documents

1 Downloads

Preview:

Click to see full reader

TRANSCRIPT

LISTS

. Single linked lists

. Double linked lists

. Stacks & Queues

. Polynomials

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 sequen-tial 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 al-

locating 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);

Pointers

Composed 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

Singly Linked Lists

bat satcat vat NULL

ptr

To insert “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 paddrCaution) step 3 must be done before step 4

Singly Linked Lists

bat satcat vat NULL

ptr

mat

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 opera-tions

Singly Linked Lists

bat satcat vat NULL

ptr

mat

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

[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 structuretypedef struct list_node *list_ptr;typedef struct list_node {

char data[4];list_ptr link;

};list_ptr ptr = NULL;

Singly Linked Lists

◦ Create new nodes for our list◦ Then place the word “bat” into our list

ptr=(list_ptr)malloc(sizeof(list_node));strcpy(ptr->data,”bat”);ptr->link=NULL;

Singly Linked Lists

b a t \0 NULL

ptr

address of

first nodeptr->data ptr->link

[two-node linked list]◦ Create a linked list of integers

typedef struct list_node *list_ptr;typedef struct list_node {

int data;list_ptr link;

};list_ptr ptr = NULL;

Singly Linked Lists

10 20 NULL

ptr

list_ptr create2() {list_ptr first, second;first = (list_ptr)malloc(sizeof(list_node));second = (list_ptr)malloc(sizeof(list_node));second->link=NULL;second->data=20;first->data=10;first->link=second;return first;

}

Singly Linked Lists

[list insertion]

◦ Determine if we have used all available memory: IS_FULL

Singly Linked Lists

10 20 NULL

ptr

node 50

temp

void insert(list_ptr *pptr,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;if(*pptr) {

temp->link = node->link;node->link = temp;

}else {

temp->link = NULL; *pptr = temp;}

}

Singly Linked Lists

[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

Singly Linked Lists

1) the node to be deleted is the first node in the list

2) otherwise

Singly Linked Lists

10 50

ptr

20 NULL

trail

10

ptr

20 NULL

node

(b) after deletion(a) before deletion

10 50

ptr

20 NULL

node

50

ptr

20 NULL

trail = NULL

(b) after deletion(a) before deletion

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

[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”);

}

Singly Linked Lists

Representing stack / queue by linked list

Dynamically LinkedStacks and Queues

NULL

top

element link

······

NULL

front

element link

······

rear

(a) linked stack

(b) linked queue

Representing N stacks by linked lists

#define MAX_STACKS 10 /* N=MAX_STACKS=10 */typedef struct {

int key;/* other fields */

} element;typedef struct stack *stack_ptr;typedef struct stack {

element item;stack_ptr link;

};stack_ptr top[MAX_STACKS];

Dynamically Linked Stacks and Queues

···

Dynamically LinkedStacks and Queues

NULL

top[0]

element link

······key

NULL

top[1]

······

NULL

top[MAX_STACKS-1]

······

◦ Initial condition for stacks top[i] = NULL, 0 £ i < MAX_STAKCS

◦ Boundary condition for n stacks Empty condition:

top[i] = NULL iff the i-th stack is empty Full condition:

IS_FULL(temp) iff the memory is full

Dynamically LinkedStacks and Queues

◦ Add to a linked stack

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 LinkedStacks and Queues

◦ Delete from a linked stackelement 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 LinkedStacks and Queues

Representing M queues by linked lists

#define MAX_QUEUES 10 /* M=MAX_QUEUES=10 */typedef struct queue *queue_ptr;typedef struct queue {

element item;queue_ptr link;

};queue_ptr front[MAX_QUEUES],rear[MAX_QUEUES];

Dynamically LinkedStacks and Queues

Dynamically LinkedStacks and Queues

NULL

front[0]

element link

······

rear[0]

key

NULL

front[1]

······

rear[1]

NULL

front[MAX_QUEUES-1]

······

rear[MAX_QUEUES-1]

·

·

·

◦ Initial conditon for queues front[i]=NULL,0 £ i < MAX_QUEUES

◦ Boundary condition for queues Empty condition:

front[i]= NULL iff the i-th 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 LinkedStacks 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 LinkedStacks 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

Dynamically LinkedStacks and Queues

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;

Polynomials

◦ poly_node

◦ a = 3x14 + 2x8 + 1

◦ b = 8x14 - 3x10 + 10x6

Polynomials

coef expon link

3 14 2 8 1 0 NULL

a

8 14 -3 10 10 6 NULL

b

◦ Adding polynomials

(a) a->expon == b->expon

Polynomials

3 14 2 8 1 0 NULL

8 14 -3 10 10 6 NULL

b

a

11 14 NULL

d rear

(b) a->expon < b->expon

Polynomials

3 14 2 8 1 0 NULL

8 14 -3 10 10 6 NULL

b

a

-3 10 NULL

d

11 14

rear

(c) a->expon > b->expon

Polynomials

3 14 2 8 1 0 NULL

8 14 -3 10 10 6 NULL

b

a

2 8 NULL

rear

11 14 -3 10

d

(d) a->expon < b->expon

Polynomials

3 14 2 8 1 0 NULL

8 14 -3 10 10 6 NULL

b

a

2 811 14 -3 10

10 6 NULL

rear

d

(e) b == NULL;

Polynomials

3 14 2 8 1 0 NULL

8 14 -3 10 10 6 NULL

b

a

2 811 14 -3 10

rear

10 6 1 0 NULL

d

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

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)

Polynomials

Allocating/deallocating nodes◦ How to preserve free node in a storage pool ?

initially link together all free nodes into a list in a stor-age pool

avail: variable of type poly_ptr that points to the first node in list of freed nodes

Polynomials

NULLavail ······

1 2 n

initial available space list

storage pool

Allocating nodespoly_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;

}

void erase(poly_ptr *pptr) {poly_ptr temp;while (*pptr) {

temp = *pptr;*pptr = (*pptr)->link;ret_node(temp);

}}

Polynomials

Traverse to the last node in the list:◦ O(n), where n: number of terms

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 node of a polynomial more effi-ciently modify list structure

◦ the link of the last node points to the first node in the list called circular list (« chain)

Polynomials

ptr

◦ Maintain our own list (as a chain) of nodes that has been freed obtain effective erase algorithmvoid cerase(poly_ptr *pptr) {

if (*pptr) {temp = (*pptr)->link;(*pptr)->link = avail;avail = temp;*pptr = NULL;

}

}

◦ Independent on the number of nodes in a list: O(1)

Polynomials

Circular list with head nodes◦ handle zero polynomials in the same way as

nonzero polynomials

Polynomials

ptrhead node

- -

ptrhead node

- -(empty list)

Inverting(or reversing) a chain “in place” by using three pointers : lead, middle, trail

typedef struct list_node *list_ptr;typedef struct list_node {

char data;list_ptr link;

};

Operations for Chains

Inverting a chainlist_ptr invert(list_ptr lead) {

list_ptr middle, trail;middle = NULL;while(lead) {

trail = middle;middle = lead;lead = lead->link;middle->link = trail;

}return middle;

}

◦ time: O(length)

Operations for Chains

Operations for Chains

NULL

leadmiddletrail

NULL

leadtrail middle

NULL

lead NULL

middle

Operations for Chains

NULL

leadmiddletrail

NULL

NULL

leadmiddletrail

NULL

NULL

leadmiddletrail

NULL

Concatenate two chains◦ Produce a new list that contains ptr1 fol-

lowed by ptr2

list_ptr concat(list_ptr ptr1,list_ptr ptr2) {list_ptr temp;if (IS_EMPTY(ptr1)) return ptr2;else {

if (!IS_EMPTY(ptr2)) {for (temp=ptr1; temp->link; temp=temp->link);temp->link = ptr2;

}return ptr1;

}

}

Operations for Chains

Finding the length of a list(chain)

int length(list_ptr ptr) {int count = 0;while (ptr) {

count++;ptr = ptr->link;

}return count;

}

Operations for Chains

Insert a new node at the front or at the rear of the chain

move down the entire length of ptr to insert rear:◦ front-insert : O(1)◦ rear-insert : O(n)

Operations for Chains

ptr x1 x2 x3 NULL

Insert a new node at the front of a list(chain)

void insert_front(list_ptr *pptr, list_ptr node) {if (IS_EMPTY(*pptr)) { *pptr = node; node->link = NULL;}else { node->link = *pptr; *pptr = node;}

}

Operations for Chains

◦ (singly) circularly linked lists

◦ insert a new node at the front or at the rear move down the entire length of ptr to insert both

front and rear: insert-front : O(n) insert-rear : O(n)

Operations forCircularly Linked Lists

ptr x1 x2 x3

◦ Improve this better: make ptr points to the last node

◦ Insert a new node at the front or at the rear front-insert : O(1) rear-insert : O(1)

Operations forCircularly Linked Lists

ptrx1 x2 x3

Insert a new node at the rear of a circular list

void insert_rear(list_ptr *pptr, list_ptr node) {if (IS_EMPTY(*pptr)) { *pptr = node; node->link = node;}else { node->link = (*pptr)->link; (*pptr)->link = node;

*pptr = node; /* for front-insert, remove this line */}

}

Operations forCircularly Linked Lists

Finding the length of a circular list

int length(list_ptr ptr) {list_ptr temp;int count = 0;if (ptr) {

temp = ptr;do {

count++;temp = temp->link;

} while (temp != ptr);

}return count;

}

Operations forCircularly Linked Lists

◦ Problems of singly linked lists move to only one way direction hard to find the previous node hard to delete the arbitrary node

because finding the previous node is hard

◦ Doubly linked circular list doubly lists + circular lists allow two links two way direction

Doubly linked lists

typedef struct node *node_ptr;typedef struct node {

node_ptr llink;element item;node_ptr rlink;

};

◦ Suppose that ptr points to any node in a doubly linked list

ptr = ptr->llink->rlink = ptr->rlink->llink

Doubly linked lists

◦ Introduce dummy node, called, head to represent empty list make easy to implement operations contains no information in item field

empty doubly linked circular list with head node

Doubly linked lists

ptr

doubly linked circular list with head node

Doubly linked lists

head node

llink item rlink

Insertion into a doubly linked circular list

void dinsert(node_ptr node,node_ptr newnode) {/* insert newnode to the right of node */newnode->llink = node;newnode->rlink = node->rlink;node->rlink->llink = newnode;node->rlink = newnode;

}

time: O(1)

Doubly linked lists

insertion into an empty doubly linked circular list

Doubly linked lists

newnode

node node

Deletion from a doubly linked circular listvoid ddelete(node_ptr node,node_ptr deleted){

/* delete from the doubly linked list */if (node == deleted)

printf(“Deletion of head node ” “not permitted.\n”);

else {deleted->llink->rlink = deleted->rlink;deleted->rlink->llink = deleted->llink;free(deleted);

}

} time complexity : O(1)

Doubly linked lists

deletion in a doubly linked list with a single node

Doubly linked lists

deleted

node

node

◦ Doubly linked circular list

don’t have to traverse a list : O(1) insert(delete) front/middle/rear is all the same

Doubly linked lists

top related