4 -1 chapter 4 queues and lists. 4 -2 queue first-in first-out (fifo) first come first serve (fcfs)...

69
4 -1 Chapter 4 Queues and Lists

Upload: kailey-loftus

Post on 16-Dec-2015

220 views

Category:

Documents


0 download

TRANSCRIPT

4 -1

Chapter 4

Queues and Lists

4 -2

Queue First-in first-out (FIFO)

First come first serve (FCFS)

2 ends: Data are inserted to one end (rear) and removed from the otherend (front).

4 -3

Linear queue ( 和課本稍不同 )

A

B

A

initial insert(A) insert(B)

rearfront

rear

front

rear

front

B

remove

rearfront

C

B

Insert(C)

rear

front

E

D

somedayrear

front

insert(F): overflow, but there are still some empty locations in the lower part.

4 -4

Abstract data type--queue abstract typedef <<eltpye>> QUEUE(eltype);

abstract empty(que) QUEUE(eltype) que; postcondition empty == (len(que) == 0);

abstract eltype remove(que) QUEUE(eltype) que; precondition empty(que) == FALSE; postcondition remove == first(que’); que == sub(que’, 1, len(que’) –1);

abstract insert(que, elt) QUEUE(eltype) que; eltype elt; postcondition que == que’ + <elt>;

4 -5

Circular queue

4

3

2

1

0

4 E

3 D

2 C

1

0

4 E

3 D

2 C

1

0 F

frontrear

initial

empty queue 之條件 : front = rear

que.items que.itemsque.rear = 4

que.front = 1 que.front = 1

que.rear = 0

(a) (b)

4 -6

Full circular queue

4 E

3 D

2 C

1 G

0 F

que.items

(c)

que.front = que.rear = 1

此時分不清是 full 或是 empty故若有 n 個記憶容量 , 則只用其中 n-1 個

4 -7

#define MAXQUEUE 100struct queue{ int items[MAXQUEUE]; int front, rear; };struct queue que;// initializationque.front = que.rear = MAXQUEUE-1;

Implementation of circular queues

4 -8

int empty(struct queue *pq){ return ((pq->front == pq->rear) ? TRUE : FALSE);} /* end empty */

Checking if empty

4 -9

int remove(struct queue *pq){ if (empty(pq)){ printf(“queue underflow”); exit(1); } /* end if */ if (pq->front == MAXQUEUE –1) pq->front = 0; else (pq->front)++; return (pq->items[pq->front]);} /* end remove */

Removing the front node

4 -10

void insert(struct queue *pq, int x){ /* make room for new element */ if (pq->rear == MAXQUEUE –1) pq->rear = 0; else (pq->rear)++; /* check for overflow */ if (pq->rear == pq->front){ printf(“queue overflow”); exit(1); } /* end if */ pq->items[pq->rear] = x; return;} /* end insert */

Appending a node

4 -11

Priority queue We can insert new elements to a priority

queue quickly. Ascending priority queue: easy to

remove the smallest item Descending priority queue : easy to

remove the largest item 最好使用 heap 做為 priority queue.

每個 stack 或 queue 個別使用固定的 array, 浪費空間多個 stack 或 queue 共用一個 array, 較節省空間

4 -12

Linear linked list

0 1 2 3 4 5 6 7 8

D A B C

-1 5 6 1

informationnext address(pointer)以 -1 代表結尾 (null pointer)

list = 2 header, external pointer

null

list

nodeinfo next

2 5 6 1**

4 -13

Operation on the first nodeA B C nul

llist

(1) adding ‘F’ to the front of the list

A B C null

list F

p = getnode();info(p) = ‘F’;next(p) = list;list = p;

(2) removing the first node of the list

B C null

list

**

4 -14

A B C null

s(top)

Linked implementation of stacks

push(s, x): similar to adding an element to the front

**

4 -15

x = pop(s): similar to removing the first node

if (empty(s)){ printf(“stack underflow”); exit(1);}else{ p = s; s = next(p); x = info(p); freenode(p);} /* end if */

p = list;list = next(p);x = info(p);freenode(p);

4 -16

Available lists

p = getnode():

if (avail == null){ rintf(“overflow”); exit(1);}p = avail;avail = next(avail);

freenode(p):

next(p) = avail;avail = p;

null

avail ...

4 -17

Linked implementation of queues

empty queue: front = rear = nullx = remove(que):

if (empty(que)){ printf(“queue underflow”); exit(1);}p = que.front;x = info(p);que.front = next(p);if (que.front == null) que.rear = null;freenode(p);return(x);

B C D null

front A

rear

front

4 -18

p

rear

x

Appending a node p = getnode(); info(p) = x; next(p) = null; if (que.rear == null) // 此時 front 也是 null que.front = p; else next(que.rear) = p; que.rear = p;

4 -19

The linked list as a data structure

insafter(p, x): Insert x into a list after a node p.

A B C

A B C

x

**

q

p

4 -20

delafter(p, x): Delete the node following p and assign its contents to x.

A B Cp

A B Cp

q

**

4 -21

Examples of list operations (1)

Delete all occurrences of the number 4: q = null; p = list; while (p != null){ if (info(p) == 4) if (q = null){ /* remove first node of the list */ x = pop(list); p = list; } else{ /* delete the node after q and move up p */ p = next(p); delafter(q, x); } /* end if */

4 -22

Examples of list operations (2)

else{ /* continue traversing the list */ q = p; p = next(p); } /* end if */ } /* end while */

4 -23

q = null; for (p = list; p != null && x > info(p); p = next(p))

q = p; /* at this point, a node containing */ /* x must be inserted */ if (q == null) /* insert x at the */ /*head of the list */ push(list, x); else insafter(q, x);

3 5 9

8q

X=8p

前面較小後面較大

Insertion of a sorted list

q p

4 -24

Header nodes( 不是一般 node, 而是特殊用途的 node)

2 A C null(1) list

此 list 有 2 個 element

(2) list A746

B841

K321

null

machine A746 是由 parts B841, K321 所組成

(3) list A C null

如果 information field 可以存放 pointer, 則可以做為 queue 之 rear.

4 -25

Array implementation of lists (1)e.g. an array of nodes containing 4 linked lists

0 26 -1

1 11 9

2 5 15

list4 = 3 1 19

list2 = 4 17 0

5 13 1

6

7 19 18

8 14 12

9 4 21

10

list3 = 11 31 7

12 6 2

13

14

15 37 23

list1 = 16 3 20

17

18 32 -1

19 18 5

20 7 8

21 15 -1

22

23 12 -1

24

25

info next info next

4 -26

Initialization of the available list

#define NUMNODES 500 struct nodetype{ int info, next; }; struct nodetype node[NUMNODES];

initialization of the available list:

avail = 0; for (i = 0; i < NUMNODES-1; i++) node[i].next = i+1; node[NUMNODES-1].next = -1;

4 -27

Allocating a node from the available list

int getnode(void) { int p; if (avail == -1){ printf("overflow\n"); exit(1); } p = avail; avail = node[avail].next; return(p); } /* end getnode */

4 -28

Returning a node to the available list

void freenode(int p){ node[p].next = avail; avail = p; return;} /* end freenode */

4 -29

insafter(p, x) Insert an item x into a list after a node p

void insafter(int p, int x){ int q; if (p == -1){ printf("void insertion\n"); return; } q = getnode(); node[q].info = x; node[q].next = node[p].next; node[p].next = q; return;} /* end insafter */

x

p

q

4 -30

delafter(p, px) Delete the node following p and store its

value in x (*px).

void delafter(int p, int *px){ int q; if ((p == -1) || (node[p].next == -1)){ printf("void deletion\n"); return; } q = node[p].next; *px = node[q].info; node[p].next = node[q].next; freenode(q); return;} /* end delafter */

A B C

p

q

4 -31

Allocating and freeing dynamic variables

int *p, *q; int x; p = (int *)malloc(sizeof(int)); *p = 3; q = p; printf("%d %d \n", *p, *q); x = 7;

3Pq

7 7Pq

x

(a) (b)

output:**

4 -32

*q = x; printf("%d %d \n", *p, *q); p = (int *) malloc(sizeof(int)); *p = 5; printf("%d %d \n", *p, *q);

7 7p

qx

5 7 7p

qx

(c) (d)

output:

**

4 -33

p = (int *)malloc(sizeof(int));*p = 5;q = (int *)malloc(sizeof(int));*q = 8;free(p);p = q;q = (int *)malloc(sizeof(int));*q = 6;printf("%d %d \n", *p, *q);

output:

5 8p

q

(a)

8p q

(b)

8p

(c)

q

6 8q p

(d)

**

4 -34

e.g.

p = (int *)malloc(sizeof(int)); *p = 3; p = (int *)malloc(sizeof(int)); *p = 7;

The first copy of *p is lost since its address was not saved.

4 -35

Linked lists with dynamic variables

struct node{ int info; struct node *next; };typedef struct node *NODEPTR;

NODEPTR getnode(void){ NODEPTR p; p = (NODEPTR)malloc(sizeof(struct node)); return(p);}void freenode(NODEPTR p){ free(p);}

4 -36

getnode and freenode can be simply replaced by:

NODEPTR p;p = (NODEPTR)malloc(sizeof(struct node));

and

free(p);

Memory allocation in C

4 -37

insafter(p, x) Insert an item x into a list after a node p

void insafter(NODEPTR p, int x){ NODEPTR q; if (p == NULL){ printf("void insertion\n"); exit(1); } q = getnode(); q->info = x; q->next = p->next; p->next = q; } /* end insafter */

x

p

q

4 -38

delafter(p, px) Delete the node following p and store its

value in x (*px)

void delafter(NODEPTR p, int *px){ NODEPTR q; if ((p == NULL) || (p->next == NULL)){ printf("void deletion\n"); exit(1); } q = p->next; *px = q->info; p->next = q->next; freenode(q);} /* end delafter */

p

q

4 -39

A queue represented as a linear list in C

Array Implementation

struct queue{ int front, rear;};struct queue que;

int empty(struct queue *pq){ return((pq->front == -1) ? TRUE : FALSE); } /* end empty */

Dynamic Implementation

struct queue{ NODEPTR front, rear;};struct queue que;

int empty(struct queue *pq){ return((pq->front == NULL) ? TRUE : FALSE);} /* end empty */

null

rearfront

4 -40

empty queue : front = rear = null

insert(q, x):

rearx

p

void insert(struct queue *pq, int x){ int p; p = getnode(); node[p].info = x; node[p].next = -1; if (pq->rear == -1) pq->front = p; else node[pq->rear].next = p; pq->rear =p;} /* end insert */

Appending a node

4 -41

void insert(struct queue *pq, int x){ NODEPTR p; p = getnode(); p->info = x; p->next = NULL; if (pq->rear == NULL) pq->front = p; else (pq->rear->next = p; pq->rear =p;} /* end insert */

4 -42

remove(q): front

int remove(struct queue *pq){ int p, x; if (empty(pq)){ printf("queue underflow\n"); exit(1); } p = pq->front; x = node[p].info; pq->front = node[p].next; if (pq->front == -1) pq->rear = -1; freenode(p); return(x); } /* end remove */

int remove(struct queue *pq){ NODEPTR p; int x; if (empty(pq)){ printf("queue underflow\n"); exit(1); } p = pq->front; x = p->info; pq->front = p->next; if (pq->front == NULL) pq->rear = NULL; freenode(p); return(x); } /* end remove */

Removing the front node

4 -43

Insertion of a sorted list

void place(NODEPTR *plist, int x){ NODEPTR p, q; q = NULL; for (p = *plist; p!= NULL && x > p->info; p = p->next) q = p; if (q == NULL) /* insert x at the head of the list */ push(plist, x); else insafter(q, x); } /* end place */

3 5 9

8q P

pq

4 -44

Dynamic and array implementation of lists

disadvantage of dynamic:need more time to allocate and free storage

advantage of dynamic: storage is allocated when needed no data type constraint need not compute address

array: 與 dynamic 相反

4 -45

Circular lists

listLastNodeFirst Node

The external pointer should point to the last node of a circular list.

4 -46

Representing a stack as a circular list

A B C

stack

int empty(NODEPTR *pstack){ return((*pstack == NULL) ? TRUE : FALSE);} /* end empty */

4 -47

void push(NODEPTR *pstack, int x){ NODEPTR p; p = getnode(); p->info = x; if (empty(pstack) == TRUE) *pstack = p; else p->next = (*pstack)->next; (*pstack)->next = p;} /* end push */

A B C D A B C

stackpush(S, 'D')

stack

Stack pushing and poping

4 -48

A B C B Cpop(s)

stack stack

int pop(NODEPTR *pstack){ int x; NODEPTR p; if (empty(pstack) == TRUE){ printf("stack underflow\n"); exit(1); } /* end if */ p = (*pstack)->next; x = p->info; if (p == *pstack) /* only one node on the stack */ *pstack = NULL; else (*pstack)->next = p->next; freenode(p); return(x); } /* end pop */

4 -49

Representing a queue as a circular list

A B C

B CA B C D

rear

front rearfront rear

front

q

insert(q, 'D')

remove(q): same as pop in a stack

q

q

4 -50

void insert(NODEPTR *pq, int x){ NODEPTR p; p = getnode(); p->info = x; if (empty(pq) == TRUE) *pq = p; else p->next = (*pq)->next; (*pq)->next = p; *pq = p; return;}insert(&q, x) is equivalent to:

push(&q, x);q = q->next;

Node insertion in the circular list

4 -51

Delafter

void delafter(NODEPTR p, int *px){ NODEPTR q; if ((p == NULL) || (p == p->next)){ /* the list is empty or contains only a single

node*/ printf("void deletion\n"); return; } /* end if */ q = p->next; *px = q->info; p->next = q->next; freenode(q); return;} /* end delafter */

...p q

4 -52

Concatenate 2 circular lists

A B C D..... .....

A B C D..... .....

list1

list1

list2

4 -53

void concat(NODEPTR *plist1, NODEPTR *plist2){ NODEPTR p; if (*plist2 == NULL) return; if (*plist1 == NULL){ *plist1 = *plist2; return; } p = (*plist1)->next; (*plist1)->next = (*plist2)->next; (*plist2)->next = p; *plist1 = *plist2; return;} /* end concat */

4 -54

null

Doubly linked listsnul

lA linear doubly linked list.

A circular doubly linked list without a header.

A circular doubly linked list with a header.

Header node

4 -55

Implementation with Cstruct node{ int info; struct node *left, *right;};typedef struct node *NODEPTR;

left(right(p)) = p = right(left(p))

4 -56

Node deletion in a doubly linked circular list

void delete(NODEPTR p, int *px){ NODEPTR q, r; if (p == NULL){ printf("void deletion\n"); return; } /* end if */ *px = p->info; q = p->left; r = p->right; q->right = r; r->left = q; freenode(p); return; } /* end delete */

A B Cq

p

r

4 -57

Node insertion to the right of node p

void insertright(NODEPTR p, int x){ NODEPTR q, r; if (p == NULL){ printf("void insertion\n"); return; } /* end if */ q = getnode(); q->info = x; r = p->right; r->left = q; q->right = r; q->left = p; p->right = q; return; } /* end insertright */

A B

D

Cq

rp

4 -58

Addition of long integers with doubly linked lists

-3 49762

21978

324

2 76941

6

The integer -3242197849762

Header

有 3 個 node 且為負數

Header

The integer 676941

0

Header

The integer 0

4 -59

How to add 2 long integers ?

(1) 決定正負號

(2) 加法運算**

4 -60

決定正負號 (1)

int compabs(NODEPTR p, NODEPTR q){ NODEPTR r, s; /* compare the counts */ if (abs(p->info) > abs(q->info)) return(1); if (abs(p->info) < abs(q->info)) return(-1); /* the counts are equal */ r = p->left; s = q->left;

4 -61

決定正負號 (2)

/* traverse the list from the most significant digits */

while (r != p){ if (r->info > s->info) return(1); if (r->info < s->info) return(-1); r = r->left; s = s->left; } /* end while */ /* the absolute value are equal */ return(0);} /* end compabs */

4 -62

加法運算NODEPTR addiff(NODEPTR p, NODEPTR q){ int count; NODEPTR pptr, qptr, r, s, zeroptr; long int hunthou = 100000L; long int borrow, diff; int zeroflag; /* initialize variables */ count = 0; borrow = 0; zeroflag = FALSE; /* generate a header node for the sum */ r = getnode(); r->left = r; r->right = r; /* traverse the two lists */ pptr = p->right; qptr = q->right; while (qptr != q){ diff = pptr->info - borrow -qptr->info;

4 -63

if (diff >= 0) borrow = 0; else{ diff = diff + hunthou; borrow = 1; } /* end if */ /* generate a new node and insert it */ /* to the left of header in sum */ insertleft(r, diff); count += 1; /* test for zero node */ if (diff == 0){ if (zeroflag == FALSE) zeroptr = r->left; zeroflag = TRUE; }else zeroflag = FALSE; pptr = pptr->right; qptr = qptr->right; } /* end while */ /* traverse the remainder of the p list */ while (pptr != p){ diff = pptr->info - borrow;

4 -64

if (diff >= 0) borrow = 0; else{ diff = diff + hunthou; borrow = 1; } /* end if */ insertleft(r, diff); count += 1; if (diff == 0){ if (zeroflag == FALSE) zeroptr = r->left; zeroflag = TRUE; }else zeroflag = FALSE; pptr = pptr->right; } /* end while */ if (zeroflag == TRUE) /* delete leading zeros */ while (zeroptr != r){ s = zeroptr; zeroptr = zeroptr->right; delete(s, &diff); count -= 1; } /* end if...while */

4 -65

/* insert count and sign into the header */ if (p->info > 0) r->info = count; else r->info = -count; return(r); } /* end addiff */

主程式 :

NODEPTR addint(NODEPTR p, NODEPTR q){ /* check if integers are of like sign */ if (p->info * q->info > 0) return(addsame(p, q)); /* check which has a larger absolute value */ if (compabs(p, q) > 0) return(addiff(p, q)); else return(addiff(q, p));} /* end addint */

4 -66

Linked lists in C++class List{ protected: struct node{ int info; struct node *next; } typedef struct node *NODEPTR; NODEPTR listptr; // the pointer to the first node // of the list public: List(); ~List(); int emptylist(); void push(int newvalue); void insertafter(int oldvalue, int newvalue); int pop(); void delete(int oldvalue); }

4 -67

List::List(){ listptr = 0;}List::~List(){ NODEPTR p, q; if (emptylist()) return 0; for (p=listptr, q=p->next; p!=0; p=q, q=p->next) delete p; }

int List:: emptylist(){ return(listptr == 0);}

List::push(int newvalue){ NODEPTR p; p = new node; p->info = newvalue; p->next = listptr; listptr = p;}

4 -68

List::insertafter(int oldvalue, int newvalue){ NODEPTR p, q; for (p=listptr; p!=0 && p->info!=oldvalue; p=p->next) ; if (p == 0); error(“ERROR: value sought is not on the list.”); q = new node; q->info = newvalue; q->next = p->next; p->next = q; }int List::pop(){ NODEPTR p; int x; if (emptylist()) error(“ERROR: the list is empty.”); p = listptr; listptr = p->next; x = p->info; delete p; return x;}

4 -69

List::delete(int oldvalue){ NODEPTR p, q; for (q=0, p=listptr; p!=0 && p->info!=oldvalue; q=p, p=p->next) ;if (p == 0) error(“ERROR: value sought is not on the list.”); if (q == 0) listptr = p->next; else q->next = p->next; delete p;}