29
1 C-C Tsai P.1 Chapter4 Linked Lists Singly Linked Lists and Chains Linked Stacks and Queues Polynomials Additional List Operations Equivalence Classes Sparse Matrices Doubly Linked Lists C-C Tsai P.2 Singly Linked Lists and Chains A list is stored in an array: If we would like to add the word mat to this list of (bat, cat, sat, vat), then we must move sat and vat one position to the right before we insert mat. Similarly, if we want to remove the word cat from the list, we must move sat and vat one position to the left to maintain our sequential representation. In general case, arbitrary insertion and deletion from arrays can be very time-consuming. A list is store in link: In a sequential representation the order of elements is the same as in the ordered list, while in a linked representation these two sequences need not be the same. To access elements of the list in the correct order with each element, we store the address, or location, of the next element in that list. Thus, associated with each list element is a node which contains both a data component and a pointer to the next item in the list. The pointers are often called links.

Chapter4 Linked Lists - 南華大學chun/DS(I)-Ch04-LinkedLists.pdf · Chapter4 Linked Lists ... A chain is a linked list in which each node represents one element. ... Circular Linked

  • Upload
    vanngoc

  • View
    262

  • Download
    0

Embed Size (px)

Citation preview

1

C-C Tsai P.1

Chapter4 Linked ListsSingly Linked Lists and ChainsLinked Stacks and QueuesPolynomialsAdditional List OperationsEquivalence ClassesSparse MatricesDoubly Linked Lists

C-C Tsai P.2

Singly Linked Lists and ChainsA list is stored in an array:

If we would like to add the word mat to this list of (bat, cat, sat, vat), then we must move sat and vat one position to the right before we insert mat.Similarly, if we want to remove the word cat from the list, we must move sat and vat one position to the left to maintain our sequential representation.In general case, arbitrary insertion and deletion from arrays can be very time-consuming.

A list is store in link: In a sequential representation the order of elements is the same as in the ordered list, while in a linked representation these two sequences need not be the same.

To access elements of the list in the correct order with each element, we store the address, or location, of the next element in that list.Thus, associated with each list element is a node which contains both a data component and a pointer to the next item in the list. Thepointers are often called links.

2

a b c d e

c a e d b

Layout of L = (a,b,c,d,e) using an array representation.

A linked representation uses an arbitrary layout.

Memory Layout

c a e d b

first

pointer (or link) in e is NULLuse a variable first to get to the first element a

link or pointer field of node

data field of node

a b c d e

NULL

first

ChainsA chain is a linked list in which each node represents one element.

There is a link or pointer from one element to the next.

The last node has a NULL (or 0) pointer

3

C-C Tsai P.5

Singly Linked ListLinked lists are drawn as an order sequence of nodes with links represented as arrows.The name of the pointer to the first node in the list is the name of the list.

The nodes do not resident in sequential locations.The locations of the nodes may change on different runs.

bat cat sat vat NULL

C-C Tsai P.6

Representing Chains in CDeclarations:typedef struct listNode *listPointer;typedef struct listNode {

char data[4];listPointer link;

}; listPointer first;

Create a new node:MALLOC (first, sizeof(*first));Empty checking:

#define IS_EMPTY(first) (!(first))Example: Strcpy(first->data, “BAT”);first->link = NULL;

link

data

4

C-C Tsai P.7

Insert an Item to Singly Linked ListIt is easier to make arbitrary insertions and deletions using a linked list rather than a sequential list.To insert the word mat between cat can sat, we must:

Get a node that is currently unused; let its address be paddr.Set the data field of this node to mat.Set paddr’s link field to point to the address found in the link field of the node containing cat.Set the link field of the node containing cat to point to paddr.

bat cat sat vat NULL

mat

bat cat sat vat NULLmat

C-C Tsai P.8

Delete an Item From Singly Linked ListTo delete mat from the list.Find the element that immediately precedes mat, which is cat, and set its link field to point to mat’s link field.

bat cat sat vat NULLmat

bat cat sat vat NULL

5

C-C Tsai P.9

Example:Inverting a Singly Linked List

x1 x2 x3 x4 x5 NULL

x1 x2 x3 x4 x5NULL

Head

Head

C-C Tsai P.10

Inverting a Singly Linked List

middle = NULL;while (lead) {

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

}return middle;

x1 x2 x3 x4 x5

First, initial the middle = NULL↑middle

NULL

↓trail

NULL

6

C-C Tsai P.11

Inverting a Singly Linked List

middle = NULL;while (lead) {

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

}return middle;

x1 x2 x3 x4 x5

First, initial the middle = NULL↑middle

NULL

↓trail

And continue loop until lead == NULL

NULL

C-C Tsai P.12

Inverting a Singly Linked List

middle = NULL;while (lead) {

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

}return middle;

x1 x2 x3 x4 x5

First, initial the middle = NULL↑middle

NULL

↓trail

And continue loop until lead == NULL

NULL

7

C-C Tsai P.13

Inverting a Singly Linked List

middle = NULL;while (lead) {

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

}return middle;

x1 x2 x3 x4 x5

First, initial the middle = NULL↑middle

NULL

↓trail

And continue loop until lead == NULL

NULL

C-C Tsai P.14

Inverting a Singly Linked List

middle = NULL;while (lead) {

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

}return middle;

x1 x2 x3 x4 x5

First, initial the middle = NULL↑middle

NULL

↓trail

And continue loop until lead == NULL

NULL

8

C-C Tsai P.15

Inverting a Singly Linked List

middle = NULL;while (lead) {

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

}return middle;

x1 x2 x3 x4 x5

First, initial the middle = NULL↑middle

NULL

↓trail

And continue loop until lead == NULL

NULL

lead == NULL, break the loop

C-C Tsai P.16

Inverting a Singly Linked List

middle = NULL;while (lead) {

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

}return middle;

x1 x2 x3 x4 x5

First, initial the middle = NULL

NULL

And continue loop until lead == NULL

NULL

↑middle

↓trail

return middle as the lead of linked listlead == NULL, break the loop

9

C-C Tsai P.17

Linked Stacks and QueuesWhen several stacks and queues coexisted, there was no efficient way to represent them sequentially.Direction of links for both stack and the queue facilitate easy insertion and deletion of nodes.

NULL

topelement link

(a) Linked Stack

NULL

frontelement link

(b) Linked queue

rear

C-C Tsai P.18

Represent n StacksDeclarations:#define MAX_STACKS 10 /* max number of stacks */typedef struct {

int key;/* other fields */} element;

typedef struct stack *stackPointer;typedef struct stack {

element item;stackPointer link;};

stackPointer top[MAX_STACKS];Initial condition:top[i] = NULL, 0 ≦ i < MAX_STACKS

Boundary conditions:top[i] = NULL iff the ith stack is emptyIsFull(temp) iff the memory is full

10

C-C Tsai P.19

Push and Pop in Linked Stackvoid push(int i, element item){ /* add an item to the top of the stack */

stackPointer temp;MALLOC (temp, sizeof (*temp));temp->data = item;temp->link = top[i];top[i]= temp;

}

element pop(int i) { /* delete an item from the stack */

stackPointer temp = top[i];element item;if (!temp) return stackEmpty();item = temp->data;top[i] = temp->link;free(temp);return item;

}

C-C Tsai P.20

Declarations:#define MAX_QUEUES 10 /* maximum number of queues */typedef struct queue *queuePointer;typedef struct queue {

element item;queuePointer link;};

queuePointer front[MAX_QUEUES], rear[MAX_QUEUES];Initial conditions:front[i] = NULL, 0 ≦ i < MAX_QUEUESBoundary conditions: front[i] = NULL iff the ith queue is empty andIsFull(temp) iff the memory is full

Represent n Queues

11

C-C Tsai P.21

void addq(element item){ /* add an item to the rear of the queue i */

queuePointer temp;MALLOC(temp, sizeof (*temp));temp->data = item;temp->link = NULL;if (front[i]) rear[i] -> link = temp;else front[i] = temp;rear[i] = temp;

}

element deleteq(int i){ /* delete an element from the queue */

queuePointer temp;element item;if (!temp) return queueEmpty();item = temp->data;front[i] = temp->link;free(temp);return item;

}

Addq and Deleteq in Linked Queue

C-C Tsai P.22

Polynomials as singly linked listsWe want to represent the polynomial:

Where the ai are nonzero coefficients and the ei are nonnegative integer exponents such that

em-1 > em-2 > … > e1 > e0 ≧ 0.

We represent each term as a node containing coefficient and exponent fields, as well as a pointer to the next term.

A x a x a x a xme

me em m( ) ...= + + +− −

− −

1 2 01 2 0

Polynomials

12

C-C Tsai P.23

Linked List for PolynomialsDeclarations:typedef struct polyNode *polyPointer;typedef struct polyNode {

int coef;int expon;polyPointer link;};

polyPointer a, b;

coef expon link

C-C Tsai P.24

Polynomial Representation

a x x= + +3 2 11 4 8

3 14 2 8 1 0a

null

b x x x= − +8 3 1014 10 6

8 14 -3 10 10 6b

null

Example1:

Example2:

13

C-C Tsai P.25

Adding PolynomialsTo add two polynomials, we examine their terms starting at the nodes pointed to by a and b.

If the exponents of the two terms are equal, we add the two coefficients and create a new term for the result. If the exponent of the current term in a is less than the exponent of the current term in b, then we create a duplicate term of b, attach this term to the result, called d, and advance the pointer to the next term in b. Take a similar action on a if a->expon > b->expon.

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

3 14 2 8 1 0a

8 14 -3 10 10 6b

11 14d

C-C Tsai P.26

Adding Polynomials (Cont’d)(b) a->expon < b->expon

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

3 14 2 8 1 0a

8 14 -3 10 10 6b

11 14d

-3 10

3 14 2 8 1 0a

8 14 -3 10 10 6b

11 14 -3 10 2 8

14

C-C Tsai P.27

Add Two PolynomialspolyPointer padd(polyPointer a, polyPointer b) /* c = a + b */{ polyPointer c, rear, temp;

int sum;MALLOC(rear, sizeof(*rear));c = rear;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;

}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 = c; c = c->link; free(temp); // Delete extra initial nodereturn c;

}

C-C Tsai P.28

Analysis of Two-polynomial Additioncoefficient additions0 ≤ additions ≤ min(m, n)where m (n) denotes the number of terms in A (B).exponent comparisonsextreme caseem-1 > fm-1 > em-2 > fm-2 > … > e0 > f0m+n-1 comparisonscreation of new nodesextreme casem + n new nodessummary O(m+n)

15

C-C Tsai P.29

Erasing Polynomialsvoid erase(polyPointer *ptr){ /* erase the polynomial pointed to by ptr */

polyPointer temp;while (*ptr) {

temp = *ptr;*ptr = (*ptr)->link;free(temp);

}}

C-C Tsai P.30

Circular Linked List Representation of PolynomialsIf the link field of the last node points to the first node in the list, all the nodes of a polynomial can be freed more efficiently.Example: ptr =3X 14+2X 8+1

Chain: A singly linked list in which the last node has a null link.Nodes that are no longer in use are freed so that we can reuse these nodes later.Maintaining a list (as a chain) of nodes that have been “freed”.

143 82 01ptr

16

C-C Tsai P.31

getNode and retNode FunctionspolyPointer getNode(void){ polyPointer node;

if (avail) {node = avail; avail = avail->link:

} else {MALLOC(node, sizeof(*node)); return node;

}}

void retNode(polyPointer pnode){ node->link = avail;

avail = node;}

C-C Tsai P.32

erase Functionvoid erase(polyPointer *ptr) /* erase the circular list ptr */ { polyPointer temp;

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

}} avail

tempptr

NULL

avail

17

C-C Tsai P.33

Polynomial with Header NodeTo avoid the special case of zero polynomial, each polynomial contains one additional head node. The expon and coef fields of this node are irrelevant.

Zero polynomial:

Polynomial:

-1a

a x x= + +3 2 114 8

3 14 2 8 1 0a -1

C-C Tsai P.34

Addition of two Polynomials with Header Nodes

polyPointer cpadd(polyPointer a, polyPointer b){ /* Adding circularly represented polynomials */

polyPointer starta, d, lastd;int sum, done = FALSE;starta = a; a = a->link; b = b->link;d = get_node(); d->expon = -1; lastd = d;do {

switch (COMPARE(a->expon, b->expon)) {case -1: attach(b->coef, b->expon, &lastd);

b = b->link; break;case 0: if (starta == a) done = TRUE;

else {sum = a->coef + b->coef;if (sum) attach(sum,a->expon,&lastd);a = a->link; b = b->link;

} break;case 1: attach(a->coef,a->expon,&lastd); a = a->link;

}} while (!done);lastd->link = d; return d; // link last node to first

}

18

C-C Tsai P.35

Additional List Operationstypedef struct listNode *listPointer;typedef struct listNode {

char data;listPointer link;

};Inverting a singly linked listlistPointer invert(listPointer lead){ /* invert the chain pointed to by lead */

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

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

}return middle;

}

C-C Tsai P.36

Concatenating Singly Linked ListslistPointer concatenate (listPointer ptr1, listPointer ptr2){ /* ptr2 is connected to the end of ptr1 list */

listPointer temp;if (!ptr1) return ptr2;if (!ptr2) return ptr1; for (temp=ptr1; temp->link; temp=temp->link) ;temp->link = ptr2;

}

19

C-C Tsai P.37

Operations for Circularly Linked ListsNeed to change the link field of the last node when insert a new node at the front of the list.

It is more convenient if the name of the circular list points to the last node.

a x2x1 x3

ax2x1 x3

C-C Tsai P.38

X1 X2 X3

(1)(2) last

Insertion for Circularly Linked ListInserting at the front of a circularly linked list.void insertFront (listPointer *last, listPointer node){ if (!(*last)) {

*last= node; node->link = node;} else {

node->link = (*last)->link; (1)(*last)->link = node; (2)

}}

20

C-C Tsai P.39

Equivalence ClassesA relation over a set, S, is said to be an equivalence relation over S iff it is symmertric, reflexive, and transitive over S.

reflexive, x=xsymmetric, if x=y, then y=xtransitive, if x=y and y=z, then x=z

C-C Tsai P.40

An Example of Equivalence ClassesWe have twelve polygons numbered 0 through 11 and the following pairs overlap:0≡4, 3≡1, 6≡10, 8≡9, 7≡4, 6≡8, 3≡5, 2≡11, 11≡0The we can partition the twelve polygons into three equivalent classes:{0,2,4,7,11}; {1,3,5}; {6,8,9,10}

21

C-C Tsai P.41

Algorithms to Find Equivalence ClassesFirst pass at equivalence algorithm

void equivalence(){ initialize;

while (there are more pairs) {read the next pair <i,j>; process this pair;

}initialize the output;do { output a new equivalence class;} while (not done);

}Detailed version of equivalence algorithmvoid equivalence(){ initialize seq to NULL and out to TRUE

while (there are more pairs) {read the next pair, <i,j>;put j on the seq[i] list; put i on the seq[j] list;

}for (i=0; i<n; i++)

if (out[i]) {out[i]= FALSE; output this equivalence class;

}}

C-C Tsai P.42

Program to Find Equivalence Classes#include <stdio.h>#include <alloc.h>#define MAX_SIZE 24#define FALSE 0#define TRUE 1typedef struct node *nodePointer ;typedef struct node {

int data;nodePointer link;

}; void main(void){ short int out[MAX_SIZE];

nodePointer seq[MAX_SIZE], x, y, top;int i, j, n;printf(“Enter the size (<= %d) “, MAX_SIZE);scanf(“%d”, &n);for (i=0; i<n; i++) {

out[i]= TRUE; seq[i]= NULL; /* Initialize seq and out */}

22

C-C Tsai P.43

Initialization of seq and out

[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11]seq

NULL

NULL

NULL

NULL NULL

NULL NULL

NULL

NULL

NULL NULL

11 3 5

1

7

0

3 8

10

4 6

9

8 6 0

24

11datalink

datalink

0 ≡ 43 ≡ 16 ≡ 108 ≡ 97 ≡ 46 ≡ 83 ≡ 52 ≡ 1111 ≡ 0

C-C Tsai P.44

Phase 1: Input the equivalence pairs/* Phase 1: input the equivalence pairs */

printf(“Enter a pair of numbers (-1 -1 to quit): “);scanf(“%d%d”, &i, &j);while (i>=0) {

MALLOC(x, sizeof(*x));x->data= j; x->link= seq[i]; seq[i]= x;MALLOC(x, sizeof(*x));x->data= i; x->link= seq[j]; seq[j]= x;printf(“Enter a pair of numbers (-1 -1 to \ quit): “);scanf(“%d%d”, &i, &j);

}

23

C-C Tsai P.45

Phase 2: Output the equivalence classes/* Phase 2: output the equivalence classes */for (i=0; i<n; i++)

if (out[i]) {printf(“\nNew class: %5d”, i);out[i]= FALSE;x = seq[i]; top = NULL;for (;;) {

while (x) {j = x->data;if (out[j]) {

printf(“%5d”, j); out[j] = FALSE;y = x->link; x->link = top; top = x; x = y;

} else x = x->link;}if (!top) break;x = seq[top->data]; top = top->link;

} /* end of for */} /* end of if */

}/ * end of main */

C-C Tsai P.46

Sparse MatricesRepresent each column of a sparse matrix as a circularly linked list with a header node. A similar representation for each row of a sparse matrix.Each node has a tag field that is used to distinguish between header nodes and entry nodes.Each header node has three additional fields: down, right, and next.

down field: links into a column listright field: links into a row listnext field: links the header nodes together

The header node for row i is also the header node for column i, and the total number of header nodes is max {number of rows, number of columns}.

next

rightheaddown

header node

24

C-C Tsai P.47

Representation of Entry NodeEach entry node has six fields: tag, row, col, down, right, value.

down field: links to the next nonzero term in the same column right field: links to the next nonzero term in the same row

A num_rows × num_cols matrix with num_terms nonzero terms needs max{num_rows, num_cols} + num_terms + 1 nodes.Total storage will be less than num_rows × num_cols when num_terms is sufficiently small.

valuerightcolrowheaddown

header node of the list of header nodes

ai j

jientry

entry of aij

C-C Tsai P.48

4 4

1 012

2 1-4

0 211

3 3-15

1 15

⎥⎥⎥⎥

⎢⎢⎢⎢

−−

1500000400001201100An Example:

25

C-C Tsai P.49

Declarations in C #define MAX_SIZE 50 /* size of largest matrix */typedef enum {head, entry} tagfield;typedef struct matrixNode *matrixPointer;typedef struct entryNode {

int row;int col;int value;

};typedef struct matrixNode {

matrixPointer down;matrixPointer right;tagfield tag;union {

matrix_pointer next;entry_node entry;

} u;};matrixPointer hdnode[MAX_SIZE];

C-C Tsai P.50

Read in a Sparse MatrixmatrixPointer mread(void){/* read in a matrix and set up its linked list. An global array hdnode is used*/

int num_rows, num_cols, num_terms; int num_heads, i; int row, col, value, current_row;matrixPointer temp, last, node;printf(“Enter the number of rows, columns and number of

nonzero terms: “);scanf(“%d%d%d”, &num_rows, &num_cols, &num_terms);num_heads = (num_cols>num_rows)? num_cols : num_rows;/* set up head node for the list of head nodes */node = new_node(); node->tag = entry;node->u.entry.row = num_rows; node->u.entry.col = num_cols;if (!num_heads) node->right = node;else { /* initialize the head nodes */

for (i=0; i<num_heads; i++) {term= new_node();hdnode[i] = temp; hdnode[i]->tag = head; hdnode[i]->right = temp; hdnode[i]->u.next = temp;

}

[0] [1] [2]

[0][1][2][3][4]

4 4 4 0 2 11 1 0 12 2 1 -4 3 3 -15

26

C-C Tsai P.51

Read in a Sparse Matrixcurrent_row= 0; last= hdnode[0];for (i=0; i<num_terms; i++) {

printf(“Enter row, column and value:”);scanf(“%d%d%d”, &row, &col, &value);if (row>current_row) {last->right= hdnode[current_row];current_row= row; last=hdnode[row];

}temp = new_node(); temp->tag=entry; temp->u.entry.row=row;temp->u.entry.col = col; temp->u.entry.value = value;last->right = temp; last= temp; /*link to row list *//* link to column list */hdnode[col]->u.next->down = temp; hdnode[col]=>u.next = temp

}last->right = hdnode[current_row]; /*close last row */for (i=0; i<num_cols; i++) /* close all column lists */

hdnode[i]->u.next->down = hdnode[i];for (i=0; i<num_heads-1; i++) /* link all head nodes together */

hdnode[i]->u.next = hdnode[i+1];hdnode[num_heads-1]->u.next= node; node->right = hdnode[0];

} return node;} O(max{#_rows, #_cols}+#_terms)

C-C Tsai P.52

Write Out a Sparse Matrixvoid mwrite(matrixPointer node){ /* print out the matrix in row major form */int i;matrixPointer temp, head = node->right;printf(“\n num_rows = %d, num_cols= %d\n”,

node->u.entry.row,node->u.entry.col);printf(“The matrix by row, column, and

value:\n\n”);for (i=0; i<node->u.entry.row; i++) {

for (temp=head->right;temp!=head;temp=temp->right)printf(“%5d%5d%5d\n”, temp->u.entry.row,

temp->u.entry.col, temp->u.entry.value);head= head->u.next; /* next row */

}}

O(#_rows+#_terms)

27

C-C Tsai P.53

Erase a Sparse Matrixvoid merase(matrixPointer *node)

{ matrixPointer x, y, head = (*node)->right;int i, num_heads;for (i=0; i<(*node)->u.entry.row; i++) {

y=head->right;while (y!=head) {

x = y; y = y->right; free(x);}x= head; head= head->u.next; free(x);

}y = head;while (y!=*node) {

x = y; y = y->u.next; free(x);}free(*node); *node = NULL;

}

O(#_rows+#_cols+#_terms)

C-C Tsai P.54

Doubly Linked ListsCan move easily only in the direction of the links in singly linked lists.Doubly linked list has at least three fields, a left link field (llink), a data field (item), and a right link field (rlink).Declarations:typedef struct node *nodePointer;typedef dtruct node {

nodePointer llink;element item;nodePointer rlink;

}

28

C-C Tsai P.55

Doubly Linked Circular ListDoubly linked circular list with head node

Empty doubly linked circular list with head node

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

ptr

Head Node

C-C Tsai P.56

Insertion into a doubly linked circular listvoid dinsert(node_pointer node, node_pointer newnode){ (1) newnode->llink = node;

(2) newnode->rlink = node->rlink;(3) node->rlink->llink = newnode;(4) node->rlink = newnode;

}Example 1:

node

newnode

node

29

C-C Tsai P.57

llink item rlink

(2)(4)(1) (3)

head node

Example 2:(1) newnode->llink = node; (2) newnode->rlink = node->rlink;(3) node->rlink->llink = newnode;(4) node->rlink = newnode;

Insertion

C-C Tsai P.58

Deletion from a doubly linked circular listvoid ddelete(node_pointer node, node_pointer deleted){ if (node==deleted)

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

(1) deleted->llink->rlink= deleted->rlink;(2) deleted->rlink->llink= deleted->llink;

free(deleted);}

}

head node

llink item rlink(1)

(2)