Queues and Lists

Download Report

Transcript Queues and Lists

Queues and Lists
Alexander G. Chefranov
CMPE-231 Spring 2012
1
Queue
A queue is an ordered collection of items from
which items may be deleted from one end (called
the front of the queue) and into which items may
be inserted at the other end ( called the rear of
the queue)
Insert(q,x) inserts item x at he rear of the queue q
X=remove(q) deletes the front element of the
queue q and sets x to its contents
Empty(q) returns false or true depending on
whether or not the queue contains any elements.
2
Queue (cont 1)
The remove operation can be applied only if the
queue is nonempty. The result of illegal
attempt to remove an element from an empty
queue is called underflow
3
The Queue as ADT
Abstract typedef <<eltype>> QUEUE(eltype);
Abstract empty(q)
QUEUE(eltype) q;
Postcondition empty==(len(q)==0);
Abstract eltype remove(q)
QUEUE(eltype) q;
Precondition empty(q)==FALSE
Postcondition remove==first(q’); q==sub(q’,1,len(q’)-1);
Abstract insert(q,elt)
QUEUE(eltype) q;
Eltype elt;
Postcondition q=q’+<elt>;
4
Implementation of Queues
#define MAXQUEUE 100
Struct queue{
int items[MAXQUEUE];
int front, rear;
} q;
If array is used, overflow is possible
Insert(q,x): q.items[++q.rear]=x;
X=remove(q): x=q.items[q.front++];
Initially; q.rear=-1; q.front=0;
The queue is empty when q.rear<q.front
The number of elements is q.rear-q.front+1
5
Implementation of Queues (cont 1)
With shifting:
X=q.itemsp[0];
For(i=0;i<q.rear;i++)
q.items[i]=q.items[i+1];
q.rear--;
View an array as a circle
Assume that q.front is the array index preceding the first
element of the queue rather than the index of the first
element itself. Thus, since q.rear is the index of the last
element of the queue, the condition q.front==q.rear
implies that the queue is empty
Initialization: q.front=q.rear=MAXQUEUE-1;
6
Implementation of Queues (cont 2)
Int empty(struct queue *pq){
return ((pq->front==pq->rear?TRUE:FALSE);
}/*end empty*
If(empty(&q)/*queue is emty*/
Else /*not empty*/
Int remove(struct queue *pq){
if(empty(pq)){printf(“queue underflow\n”);
exit(1);
}/*end if*/
if(pq->front==MAXQUEUE-1)pq->front=0;
else (pq->front)++;
return (pq->items[pq->front]);
}/*end remove*/
7
Implementation of Queues (cont 3)
Void insert(struct queue *pq, int x){
if (pq->rear==MAXQUEUE-1) pq->rear=0;
else pq->rear++;
/*check for overflow*/
if(pq->rear==pq->front){printf(“queue overflow\n”);
exit(1);
}/*end if*/
pq->items[pq->rear]=x;
return;
}/*end insert*/
8
Priority Queue
The priority queue is a data structure in which the intrinsic ordering of
the elements does determine the results of its basic operations
An ascending (descending) priority queue is a collection of items into
which items can be inserted arbitrarily and from which only the
smallest (largest) item can be removed
Pqinsert(apq,x), pqmindelete(apq);
Pqinsert(dpq, x), pqmaxdelete(dpq);
Empty(pq)
Stack may be viewed as a descending priority queue whose elements
are ordered by time of insertion
A queue may be viewed as an ascending priority queue whose
elements are ordered by time of insertion.
In both cases, the time of insertion is not part of the elements
themselves but is used to order the priority queue
9
Array Implementation of a Priority
Queue
Possible solutions to organize ascending queue
1. A special empty symbol can be placed into a
deleted position
2. A new item is inserted in the first empty
position
3. Shifting after deletion
4. Maintain the priority queue as an ordered,
circular array
10
Linked Lists
Linear linked list: each item in the list is called a node and
contains two fields, an information field and a next address
field (pointer)
The null pointer signals the end of the list
The list with no nodes is the empty list or null list: the external
pointer list=null
P is a pointer to a node, node(p) refers to the node pointed by
p, info(p) refers to the information portion of that node,
next(p) refers to the next address portion and is therefore a
pointer
If next(p) is not null, info(next(p)) refers to the information
portion of the node that follows node(p) in the list
11
Inserting and Removing Nodes from a
List
P=getnode() obtains an empty node and sets p to the address
of that node
Insertion:
Info(p)=x;
Next(p)=list;
List=p;
Deletion:
P=list;
List=next(p);
X=info(p);
Freenode(p);
12
Getnode and Freenode Operations
Real memory is finite and reuse is meaningful
P=getnode():
If(avail==null){ printf(“overflow\n”);
exit(1);
}
P=avail;
Avail=next(avail);
Freenode(p):
next(p)=avail;
avail=p;
13
Linked Implementation of Queues
X=remove(q):
If(empty(q)){ printf(“queue underflow\n”);
exit(1);
}
P=q.front;
X=info(p);
q.front=next(p);
If(q.front==null)q.rear=null;
Freenode(p);
Return(x);
14
Linked Implementation of Queues
(cont 1)
Insert(q,x):
P=getnode();
Info(p)=x;
Next(p)=null;
If(q.rear==null) q.front=p;
Else next(q.rear)=p;
q.rear=p;
15
Array Implementation of Lists
#define NUMNODES 500
Struct nodetype{
int info, next;
};
Struct nodetype node[NUMNODES];
Initially, all nodes are unused:
Avail=0;
for(i=0;i<NUMNODES;i++)
node[i].next=i+1;
Node[NUMNODES-1].next=-1;
Void getnode(void){
int p;
if(avail==-1){
printf(“overflow\n”); exit(1);
}
16
Array Implementation of Lists
P=avail;
avail=node[avail].next;
return p;
}/*end getnode*/
Void freenode(int p){
node[p].next=avail;
avail=p;
return;
}/*end freenode*/
Void insafter(int p, int x){
int q;
if(p==-1){ printf(“void insertion\n”); return;
}
q=getnode();
17
Array Implementation of Lists
node[q].info=x;
node[q].next=node[p].next;
node[p].next=q;
return;
}/*end insafter*/
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;
}
18
Linked Lists Using 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);
}
19
Linked Lists Using Dynamic
Variables
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*/
20
Linked Lists Using Dynamic
Variables
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);
}
21
Struct queue{
int front, rear’
};
Struct queue q;
Queues as Lists in C
Struct queue{
NODEPTR front, rear;
};
Struct queue q;
Int empty(struct queue *pq){
return((pq->front==-1) TRUE: FALSE);
}/*end empty*/
Int struct(struct queue *pq){
return ((pq->front==NULL)?TRUE:FALSE);
}/*end empty*/
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*/
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*/
22
Queues as Lists in C
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*/
23
Circular Lists
If the last node in a linear list refers to the first
node then it is a circular list
Let an external pointer, p, refers to the last node
in the list. Then the last node is node(p), and
the first node is node(next(p))
24
Stack as a Circular List
Let stack be a pointer to the last node of a
circular list and let the first node is the top of
the stack
An empty stack is represented by a null list
Int empty(NODEPTR *pstack){
return ((*pstack==NULL)?TRUE:FALSE);
}/*end empty*/
25
Stack as a Circular List
Void push(NODEPTR *pstack, int x){
NODEPTR p;
p=getnode();
p->info=x;
if(empty(pstack)) *pstack=p;
else p->next=(*pstack)->next;
(*pstack)->next=p;
}/*end push*/
26
Stack as a Circular List
Int pop(NODEPTR *pstack){
int x;
NODEPTR p;
if(empty(pstack)){
printf(“stack underflow\n”); exit(1);
}
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*/
27
Queue as a Circular List
Using a circular list, a queue may be specified by
a single pointer, q, to that list. Node(q) is the
rear of the queue and the following node is
the front
The function empty is the same as for stacks.
The routine remove(pq) called by remove(&q)
is identical to pop except that all references
are to pstack are replaced by pq, a pointer to
q.
28
Queue as a Circular List
Void insert(NODEPTR *pq, int x){
NODEPTR p;
p=getnode();
p->info=x;
if(empty(pq)) *pq=p;
else p->next=(*pq)->next;
(*pq)->next=p;
*pq=p;
return;
}/*end insert*/
Note that insert(&q,x) is equivalent to
push(&q,x);
q=q->next;
29
Doubly Linked Lists
Struct nodetype{
int info;
int left, right;
};
Struct nodetype node[NUMNODES];
Struct node{
int info;
struct node *left, *right;
};
Typedef struct node *NODEPTR;
30