Post on 16-Dec-2015
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 -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 -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 -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;}