Chpater 5: Queues

Chapter 5: Queues

1. Queues

A queue is an ordered list in which insertion are done at rear and deletions are done at front. The first element to be inserted is the first one to be deleted. Hence, it is called First in First out (FIFO) or Last on Last out (LILO) list.


2. Applications

  • Operating systems schedule jobs (with equal priority) in the order of arrival
  • Multi-programming
  • Asynchronous data transfer (file IO, pipes, sockets)
  • Any first-come first-served scenario
  • Auxiliary data structure for algorithms
  • Component of other data structures

3. Implementation

Simple Circular Array Implementation

struct ArrayQueue{
	int front, rear;
	int capacity;
	int *array;
};
struct ArrayQueue *Queue(int size){
	struct ArrayQueue *Q=malloc(sizeof(struct ArrayQueue));
	if(!Q) return NULL;
	Q->capacity=size;
	Q->front=Q->rear=-1;
	/*in this version, we initialize the pointers both at -1*/ 
	/*and index -1 is a NULL element space sacrifice for convention*/
	Q->array=malloc(Q->capacity * (sizeof(int));
	if(!Q->arrray)	return NULL;
	return Q;
}
int IsEmptyQueue(struct ArraQueue *Q){
	return (Q->front==-1);
}
int IsFullQueue(struct ArrayQueue *Q){
	return ((Q->rear +1) % Q->capacity == Q->front); 						//IMP: (rear+1)%MaxSize==front ?
}	
int QueueSize(){
	return (Q->capacity - Q->front + Q->rear + 1) % Q->capacity;			//IMP: (MaxSize-front+rear+1)%MaxSize
}
void EnQueue(struct ArrayQueue *Q, int data){
	if(IsFullQueue(Q))
		printf("Queue Overflow");
	else{
		Q->rear=(Q->rear +1) % Q->capacity;
		Q->array[Q->rear]=data;
		if(Q->front==-1)						//first element enQueue, forward the front pointer
			Q->front=Q->rear;	
	}
}
int DeQueue(struct ArrayQueQue *Q){
	int data;
	if(IsEmptyQueue(Q)){
		printf("Queue is empty");
		return 0;
	}
	else{
		data=Q->array[front];
		if(Q->front==Q->rear)
			Q->front=Q->rear=-1;				//only one element in queue
		else
			Q->front=(Q->front +1) % Q->capacity;
	}
	return data;
}
void DeleteQueue(struct ArrayQueue *Q){
	if(Q){	
		if(Q->array)
			free(Q->array);
		free(Q);
	}
}			
/*another version with different pointers' assignment*/
struct ArrayQueue *Queue(int size){
	struct ArrayQueue *Q=malloc(sizeof(struct ArrayQueue));
	if(!Q) return NULL;
	Q->capacity=size;
	Q->front=Q->rear=0;
	/*in this version, we initialize the pointers both at 0*/ 
	/*front: point to the first element*/
	/*rear: point to the next position of last element*/
	Q->array=malloc(Q->capacity * (sizeof(int));
	if(!Q->arrray)	return NULL;
	return Q;
}
int IsEmptyQueue(struct ArraQueue *Q){
	return (Q->front==Q->front);
}
int IsFullQueue(struct ArrayQueue *Q){
	return ((Q->rear +1) % Q->capacity == Q->front); 
}	
int QueueSize(){
	return (Q->capacity - Q->front + Q->rear) % Q->capacity;							//no'+1' operation
}

Dynamic Circular Array Implementation

struct DynArrayQueue{
	int front, rear;
	int capacity;
	int *array;
};
struct DynArrayQueue *CreateDynQueue(){
	struct DynArrayQueue *Q=malloc(sizeof(struct DynArrayQueue));
	if(!Q) return NULL;
	Q->capacity=1;
	Q->front=Q->rear=-1;
	Q->array=malloc(Q->capacity * sizeof(int));
	if(!Q->array) return NULL;
	return Q;
}
int IsEmptyQueue(struct DynArrayQueue *Q){
	return (Q->front==-1);
}
int IsFullQueue(struct DynArrayQueue *Q){
	return ((Q->rear +1) % Q->capacity == Q->front);
int QueueSize(){
	return (Q->capacity - Q->front + Q->rear + 1) % Q->capacity;
}
void EnQueue(struct DynArrayQueue *Q, int data){
	if(IsFullQueue(Q))
		ResizeQueue(Q);
	Q->rear = (Q->rear + 1) % Q->capacity;
	Q->array[Q->rear] = data;
	if(Q->front==-1)											//enqueue first element
		Q->front = Q->rear;
}
void ResizeQueue(struct DynArrayQueue *Q){
	int size=Q->capacity;
	Q->capacity=Q->capacity * 2;
	Q->array=realloc(Q->array, Q->capacity);
	if(!Q->array){
		printf("Memory Error");
		return;
	}
	if(Q->front > Q->rear){
		for(int i=0; i<Q->front; i++)
			Q->array[i+size]=Q->array[i];
	Q->rear = Q->rear + size;
}
int DeQueue(struct DynArrayQueue *Q){
	int data;
	if(IsEmptyQueue(Q)){
		printf("Queue is empty");
		return 0;
	}
	else{
		data=Q->array[Q->front];
		if(Q->front==Q->rear)
			Q->front=Q->rear=-1;
		else
			Q->front=(Q->front + 1) % Q->capacity;
	}
	return data;
}
void DeleteQueue(struct DynArrayQueue *Q){
	if(Q){
		if(Q->array)
			free(Q->array);
		free(Q);
	}	
}	

Linked List Implementation

struct ListNode{
	int data;
	struct ListNode *next;
};
struct Queue{
	struct ListNode *front;
	struct ListNode *rear;
};
struct Queue *CreateQueue(){
	struct Queue *Q;
	struct ListNode *temp;
	Q=malloc(sizeof(struct Queue));
	if(!Q) return NULL;
	temp=malloc(sizeof(struct ListNode));
	Q->front=Q->rear=NULL;
	return Q;
}
int IsEmptyQueue(struct Queue *Q){
	return (Q->front==NULL);
}
void EnQueue(struct Queue *Q, int data){
	struct ListNode *newNode;
	newNode=malloc(sizeof(struct ListNode));
	if(!newNode) return NULL;
	newNode->data=data;
	newNode->next=NULL;
	if(Q->rear)
		Q->rear->next=newNode;
	Q->rear=newNode;
	if(Q->front==NULL)
		Q->front=Q->rear;
}
int DeQueue(struct Queue *Q){
	int data;
	struct ListNode *temp;
	if(IsEmptyQueue(Q)){
		printf("Queue is empty");
		return 0;
	}
	else{
		temp=Q->front;
		data=Q->front->data;
		Q->front==Q->front->next;
		free(temp);
	}
	return data;
}
void DeleteQueue(struct Queue *Q){
	struct ListNode *temp;
	while(Q){
		temp=Q;
		Q=Q->next;
		free(temp);
	}
	free(Q);
}

4. Queues: Problems & Solutions

Pro 1.1: Reverse a Queue

Solution : auxiliary stack

void ReverseQueue(struct Queue *Q){
	struct Stack *S=CreateStack();
	while(!IsEmptyQueue(Q))
		Push(S, DeQueue(Q));
	while(!IsEmptyStack(Q))
		EnQueue(Q, Pop(S));
}

Pro 1.2: Reverse first k elements of a queue

Given an integer k and a queue of integers, how to reverse the order of the first k elements of the queue, leaving the other elements in the same relative order.
Queue: [1, 2, 3, 4, 5, 6, 7, 8, 9] k=4, to [4, 3, 2, 1, 5, 6, 7, 8, 9]

Solution :

void reverseQueueK(struct Queue *q, int k){
	if(q==NULL || k>QueueSize(q)) return ;
	else if(k>0){
		struct Stack *s=CreateStack();
		for(int i=0; i<k i++)
			Push(s, DeQueue(q));
		while(!IsEmptyStack(s)
			EnQueue(q, Pop(s));
		for(int i=0; i<QueueSize(q)-k; i++)
			EnQueue(q, DeQueue(q));						//wrap around rest of elements
	}
}

Pro 2.1: Implement a Queue using stacks

Solution :

struct Queue{
	struct Stack *s1;
	struct Stack *s2;
};
void EnQueue(struct Queue *Q, int data){
	Push(Q->s1,data);								//push into stack1
}
int DeQueue(struct Queue *Q){
	if(!IsEmptyStack(Q->s2))
		return Pop(Q->s2);							//pop at stack2
	else{
		while(!IsEmptyStack(Q->s1))					
			Push(Q->s2,Pop(Q->s1));					//push s1 element into s2
		return Pop(Q->s2);
	}
}

Pro 2.2: Implement a Stack using queues

Solution :

struct Stack{
	struct Queue *q1;							//store elements
	struct Queue *q2;							//hold temporarily during pop and top methods
};
void Push(struct Stack *s, int data){
	if(IsEmptyQueue(s->q1))						
		EnQueue(s->q2, data);					//if q1 empty, enqueue element into q2
	else
		EnQueue(s->q1, data);					//otherwise, enqueue element into q1
}
int Pop(struct Stack *s){
	if(IsEmptyQueue(s->q2)){					//if q2 empty
		int size=QueueSize(s->q1);
		for(int i=0; i<size-1; i++)				//transfer element from q1 to q2
			EnQueue(s->q2,DeQueue(s->q1));	
		return DeQueue(s->q1);					//the last element left in the q1 is the top element on the stack
	}
	else{
		int size=QueueSize(s->q2);
		for(int i=0; i<size-1; i++)
			EnQueue(s->q1, DeQueue(s->q2));
		return DeQueue(s->q2);
	}
}

Pro 3: Maximum Sum in Sliding Window

Given array A[] with sliding window of size w which is moving from the very left of the array to the very right. Assume that we can only see the w numbers in the window. Each time the sliding window moves rightwards by one position.

Solution : Doubly Ended Queue

  • Refer to Priority Queues

Pro 4: Give a Formula in terms of rear, front and n

A queue is set up in a circular array A[0…n-1] with front and rear defined as usual. Assume that n-1 locations in the array are available for storing the elements with the other element being used to detect full/empty condition. Give a formula for the number of elements in terms of rear, front, and n.
在这里插入图片描述

Solution :

  • Rear of the queue is somewhere clockwise from the front.
  • To enqueue an element, we move rear one position (+1) clockwise and write the element in that position.
  • To dequeue an element, we simply move front one position (+1) clockwise.
  • Queue migrates in a clockwise direction as we enqueue and dequeue.
  • Emptiness and fullness to be checked carefully.
  • Analyze the possible situations, we will get:
			Number of Element = rear - front + 1 ,				 if rear == front
			  		 		  = rear - front + n , 				 otherwise		

Pro 5: Implement Doubly Ended Queues

Solution :

void pushBackDEQ(struct ListNode **head, int data){
	struct ListNode *newNode=(struct ListNode*)malloc(sizeof(struct ListNode));
	newNode->data=data;
	if(*head==NULL){
		*head=newNode;
		(*head)->next=*head;
		(*head)->prev=*head;
	}
	else{
		newNode->prev=(*head)->prev;
		newNode->next=*head;
		(*head)->prev->next=newNode;
		(*head)->prev=newNode;
	}
}
void pushFrontDEQ(struct ListNode **head, int data){
	pushBackDEQ(head, data);
	*head=(*head)->prev;
}
int popBackDEQ(struct ListNode **head){
	int data;
	if((*head)->prev==*head){
		data=(*head)->data;
		free(*head);
		*head=NULL;
	}
	else{
		struct ListNode *newTail=(*head)->prev->prev;
		data=(*head)->prev->data;
		newTail->next=*head;
		free((*head)->prev);
		(*head)->prev=newTail;
	}
	return data;
}
int popFrontDEQ(struct ListNode **head){
	int data;
	*head=(*head)->next;
	data=popBackDEQ(head);
	return data;
}	

Pro 6: Check whether each Successive Pair is Consecutive or not

Given a stack of integers, how to check whether each successive pair of numbers in the stack is consecutive or not. If the stack has an odd number of elements, the element at the top is left out of a pair.

Solution :

int checkStackPair(struct Stack *s){
	struct Queue *q=CreateQueue();
	int pairwiseOrder=1
	while(!IsEmptyStack(s))
		EnQueue(q, Pop(s);
	while(!IsEmptyQueue(q))
		Push(s, DeQueue(q));
	while(!IsEmptyStack(s)){
		int temp1=Pop(s);
		EnQueue(q, temp1)
		if(!IsEmptyStack(s)){
			int temp2=Pop(s);
			EnQueue(q, temp2);
			is(abs(n-m)!=1)
				pairwiseOrder=0;
		}
	}	
	while(!IsEmptyQueue(q))
		Push(s, Dequeue(q));
	return pairwiseOrder;
}		

Pro 7: Rearrange the Elements by Interleaving

Queue: [11, 12, 13, 14, 15, 16, 17, 18, 19, 20] to [11, 16, 12, 17, 13, 18, 14, 19, 15, 20]

Solution :

void interleavingQueue(struct Queue *q){		//only use 1 stack, need multi-times transforms to ensure the order
	if(QueueSize(q) % 2 != 0) return;
	struct Stack *s=CreateStack();				
	int half=QueueSize(q)/2;					// Q <[a1 a2 b1 b2]<
	for(int i=0; i<half; i++)
		Push(s, DeQueue(q));					// S ><[a2 a1]   Q <[b1 b2]<
	while(!IsEmptyStack(s))
		EnQueue(q, Pop(s));						// Q <[b1 b2 a2 a1]<
	for(int i=0; i<half; i++)
		EnQueue(q, DeQueue(q));					// Q <[a2 a1 b1 b2]<
	for(int i=0; i<half; i++)
		Push(s, DeQueue(q));					// S ><[a1 a2]  Q <[b1 b2]<
	while(!IsEmptyStack(s)){
		EnQueue(q, Pop(s));						// while1: S ><[a2] Q <[b1 b2 a1]< -----S ><[a2] Q <[b2 a1 b1]<
		EnQueue(q, DeQueue(q));					// while2: S [] Q <[b2 a1 b1 a2]< ----S [] Q <[a1 b1 a2 b2]<
	}
}	
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值