Chapter 4 Queues and Lists 4 1 Queue






![Implementation of circular queues #define MAXQUEUE 100 struct queue{ int items[MAXQUEUE]; int front, rear; Implementation of circular queues #define MAXQUEUE 100 struct queue{ int items[MAXQUEUE]; int front, rear;](https://slidetodoc.com/presentation_image/5640840092d1e9334209194c056ac3a7/image-7.jpg)




















![Returning a node to the available list void freenode(int p) { node[p]. next = Returning a node to the available list void freenode(int p) { node[p]. next =](https://slidetodoc.com/presentation_image/5640840092d1e9334209194c056ac3a7/image-28.jpg)









































- Slides: 69
Chapter 4 Queues and Lists 4 -1
Queue n First-in first-out (FIFO) n First come first serve (FCFS) n 2 ends: Data are inserted to one end (rear) and removed from the other end (front). 4 -2
Linear queue (和課本稍不同) initial insert(A) insert(B) B remove rear front A rear A front Insert(C) rear front someday E rear D C B n rear front B front insert(F): overflow, but there are still some empty locations in the lower part. 4 -3
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 -4
Circular queue initial 4 front rear 3 empty queue 之條件: front = rear 2 1 0 que. items 4 E 3 2 que. items que. rear = 4 4 E D 3 D C 2 C que. front = 1 1 0 0 (a) que. front = 1 1 F (b) que. rear = 0 4 -5
Full circular queue que. items 4 E 3 D 2 C 1 G 0 F que. front = que. rear = 1 (c) 此時分不清是 full 或是 empty 故若有 n 個記憶容量, 則只用其中 n-1 個 4 -6
Implementation of circular queues #define MAXQUEUE 100 struct queue{ int items[MAXQUEUE]; int front, rear; }; struct queue que; // initialization que. front = que. rear = MAXQUEUE-1; 4 -7
Checking if empty int empty(struct queue *pq) { return ((pq->front == pq->rear) ? TRUE : FALSE); } /* end empty */ 4 -8
Removing the front node 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 */ 4 -9
Appending a node 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 */ 4 -10
Priority queue n n n 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 -11
Linear linked list 0 1 2 D -1 3 5 6 A B C 5 6 1 list = 2 2 4 7 8 information next address(pointer) 以-1代表結尾 (null pointer) header, external pointer 5 6 1 null list node ** info next 4 -12
Operation on the first node list A B C null (1) adding ‘F’ to the front of the list F A B C null p = getnode(); info(p) = ‘F’; next(p) = list; list = p; (2) removing the first node of the list B C null ** 4 -13
Linked implementation of stacks s A (top) B C null push(s, x): similar to adding an element to the front ** 4 -14
x = pop(s): similar to removing the first node if (empty(s)) { printf(“stack underflow”); exit(1); } p = list; else{ list = next(p); p = s; x = info(p); s = next(p); freenode(p); x = info(p); freenode(p); } /* end if */ 4 -15
Available lists avail . . . null p = getnode(): freenode(p): if (avail == null){ rintf(“overflow”); exit(1); } p = avail; avail = next(avail); next(p) = avail; avail = p; 4 -16
Linked implementation of queues front A B C empty queue: front = rear = null D null rear x = remove(que): if (empty(que)){ printf(“queue underflow”); exit(1); } p = que. front; x = info(p); front que. front = next(p); if (que. front == null) que. rear = null; freenode(p); return(x); 4 -17
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; p x rear 4 -18
The linked list as a data structure n insafter(p, x): Insert x into a list after a node p. A B C p A C B x q ** 4 -19
n delafter(p, x): Delete the node following p and assign its contents to x. p A B C p A q ** 4 -20
Examples of list operations (1) n 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 -21
Examples of list operations (2) else{ /* continue traversing the list */ q = p; p = next(p); } /* end if */ } /* end while */ 4 -22
Insertion of a sorted list 3 5 q 9 p q 8 X=8 前面較小 後面較大 p q = null; for (p = list; p != null p = next(p)) q = p; /* at this point, a node /* x must be inserted */ if (q == null) /* insert /*head of push(list, x); else insafter(q, x); && x > info(p); containing */ x at the */ the list */ 4 -23
Header nodes (不是一般node, 而是特殊用途的 node) (1) list 2 A C null 此 list 有 2 個 element (2) list A 746 B 841 K 321 null machine A 746 是由 parts B 841, K 321 所組成 (3) list A C null 如果 information field 可以存放 pointer, 則可以做為 queue 之 rear. 4 -24
Array implementation of lists (1) e. g. an array of nodes containing 4 linked lists info next 0 26 -1 13 1 11 9 14 2 5 15 15 37 23 list 4 = 3 1 19 list 1 = 16 3 20 list 2 = 4 17 0 17 5 13 1 18 32 -1 19 18 5 6 7 19 18 20 7 8 8 14 12 21 15 -1 9 4 21 22 12 -1 23 10 list 3 = 11 31 7 24 12 6 2 25 4 -25
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 -26
Allocating a node from the available list int getnode(void) { int p; if (avail == -1){ printf("overflown"); exit(1); } p = avail; avail = node[avail]. next; return(p); } /* end getnode */ 4 -27
Returning a node to the available list void freenode(int p) { node[p]. next = avail; avail = p; return; } /* end freenode */ 4 -28
insafter(p, x) n Insert an item x into a list after a node p void insafter(int p, int x) { int q; if (p == -1){ printf("void insertionn"); return; p } q = getnode(); node[q]. info = x; node[q]. next = node[p]. next; node[p]. next = q; return; } /* end insafter */ x q 4 -29
delafter(p, px) n 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 deletionn"); return; p } q = node[p]. next; A B C *px = node[q]. info; q node[p]. next = node[q]. next; freenode(q); return; } /* end delafter */ 4 -30
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; output: x P q 3 (a) P q 7 ** 7 (b) 4 -31
*q = x; printf("%d %d n", *p, *q); p = (int *) malloc(sizeof(int)); *p = 5; printf("%d %d n", *p, *q); output: q p q x 7 (c) 7 ** p 5 x 7 7 (d) 4 -32
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: p 5 q 8 p q (a) p q (c) ** 8 (b) 8 q 6 p 8 (d) 4 -33
e. g. p = (int *)malloc(sizeof(int)); *p = 3; p = (int *)malloc(sizeof(int)); *p = 7; n The first copy of *p is lost since its address was not saved. 4 -34
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 -35
Memory allocation in C getnode and freenode can be simply replaced by: NODEPTR p; p = (NODEPTR)malloc(sizeof(struct node)); and free(p); 4 -36
insafter(p, x) n Insert an item x into a list after a node p void insafter(NODEPTR p, int x) { NODEPTR q; if (p == NULL){ printf("void insertionn"); exit(1); } p q = getnode(); q->info = x; q->next = p->next; x p->next = q; q } /* end insafter */ 4 -37
delafter(p, px) n 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 deletionn"); exit(1); } q = p->next; p *px = q->info; p->next = q->next; q freenode(q); } /* end delafter */ 4 -38
A queue represented as a linear list in C null front rear Array Implementation Dynamic Implementation struct queue{ int front, rear; }; struct queue que; struct queue{ NODEPTR front, rear; }; struct queue que; int empty(struct queue *pq) { return((pq->front == 1) ? TRUE : FALSE); } /* end empty */ int empty(struct queue *pq) { return((pq->front == NULL) ? TRUE : FALSE); } /* end empty */ 4 -39
Appending a node empty queue : front = rear = null p insert(q, x): x rear 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 */ 4 -40
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 -41
Removing the front node remove(q): front int remove(struct queue *pq) { int p, x; int remove(struct queue *pq) { NODEPTR p; int x; if (empty(pq)){ printf("queue underflown"); exit(1); } } p = pq->front; x = node[p]. info; x = p->info; pq->front = node[p]. next; pq->front = p->next; if (pq->front == -1) if (pq->front == NULL) pq->rear = -1; pq->rear = NULL; freenode(p); return(x); 4 -42 } /* end remove */
Insertion of a sorted list 3 q 5 9 P q 8 p 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 */ 4 -43
Dynamic and array implementation of lists n n n 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 -44
Circular lists list First Node Last Node The external pointer should point to the last node of a circular list. 4 -45
Representing a stack as a circular list stack A B C int empty(NODEPTR *pstack) { return((*pstack == NULL) ? TRUE : FALSE); } /* end empty */ 4 -46
Stack pushing and poping stack A B C push(S, 'D') D A B 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 */ C 4 -47
stack A B pop(s) C int pop(NODEPTR *pstack){ int x; NODEPTR p; if (empty(pstack) == TRUE){ printf("stack underflown"); 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 */ stack B C 4 -48
Representing a queue as a circular list front A rear C B q remove(q): same as pop in a stack insert(q, 'D') front A B C rear D q front B rear C q 4 -49
Node insertion in the circular list 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; 4 -50
Delafter p q . . . 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 deletionn"); return; } /* end if */ q = p->next; *px = q->info; p->next = q->next; freenode(q); return; } /* end delafter */ 4 -51
Concatenate 2 circular lists list 1 A . . . B list 2 C . . . D list 1 A . . . B C . . . D 4 -52
void concat(NODEPTR *plist 1, NODEPTR *plist 2) { NODEPTR p; if (*plist 2 == NULL) return; if (*plist 1 == NULL){ *plist 1 = *plist 2; return; } p = (*plist 1)->next; (*plist 1)->next = (*plist 2)->next; (*plist 2)->next = p; *plist 1 = *plist 2; return; } /* end concat */ 4 -53
Doubly linked lists null A linear doubly linked list. A circular doubly linked list without a header. Header node A circular doubly linked list with a header. 4 -54
Implementation with C struct node{ int info; struct node *left, *right; }; typedef struct node *NODEPTR; left(right(p)) = p = right(left(p)) 4 -55
Node deletion in a doubly linked circular list void delete(NODEPTR p, int *px) { NODEPTR q, r; if (p == NULL){ printf("void deletionn"); return; } /* end if */ p *px = p->info; A B q = p->left; q r = p->right; q->right = r; r->left = q; freenode(p); return; } /* end delete */ C r 4 -56
Node insertion to the right of node p void insertright(NODEPTR p, int x) { NODEPTR q, r; if (p == NULL){ printf("void insertionn"); return; } /* end if */ q = getnode(); q->info = x; r = p->right; B A q r->left = q; p D q->right = r; q->left = p; p->right = q; return; } /* end insertright */ C r 4 -57
Addition of long integers with doubly linked lists Header -3 49762 21978 324 The integer -3242197849762 有 3 個 node 且為負數 Header 2 76941 6 The integer 676941 Header 0 The integer 0 4 -58
How to add 2 long integers ? (1)決定正負號 (2)加法運算 ** 4 -59
決定正負號 (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 -60
決定正負號 (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 -61
加法運算 NODEPTR addiff(NODEPTR p, NODEPTR q) { int count; NODEPTR pptr, qptr, r, s, zeroptr; long int hunthou = 100000 L; 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 -62
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 -63
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 -64
/* 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 -65
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 -66
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 -67
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 -68 }
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; } 4 -69