数据结构–队列
一. 队列–用数组实现时出现的问题
_Bool offerQueue(ArrayQueue queue,int element)
{
if(queue->front+1==queue->rear) return 0;
queue->rear++;
queue->array[queue->rear]=element;
return 1;
}
错误1. if(queue->front+1==queue->rear) return 0;
如图,实际上这种实现方式就是数组,你末尾下标加1怎么能等于头呢
应该这样判断:
if((queue->rear + 1) % queue->capacity == queue->front)
下一行queue->rear后移同理:
queue->rear = (queue->rear + 1) % queue->capacity;
问题2. 先存/取值,再变下标!
初始状态(队空条件):Q->front == Q->rear == 0。
进队操作:队不满时,先送值到队尾元素,再将队尾指针加1。
出队操作:队不空时,先取队头元素值,再将队头指针加1。
队列到底是先取值再变下标还是都可以???
3. 较完整代码
//循环队列
#include <bits/stdc++.h>
using namespace std;
typedef int E;
struct Queue {
E * array;
int capacity; //数组容量
int rear, front; //队尾、队首指针
};
typedef struct Queue * ArrayQueue;
bool initQueue(ArrayQueue queue){
queue->array = (int*)malloc(sizeof(E) * 10);
if(queue->array == NULL) return 0;
queue->capacity = 10;
queue->front = queue->rear = 0; //默认情况下队首和队尾都指向0的位置
return 1;
}
_Bool offerQueue(ArrayQueue queue,int element)
{
if((queue->rear+1)%queue->capacity==queue->front) return 0;
queue->array[queue->rear]=element;
queue->rear = (queue->rear + 1) % queue->capacity;
return 1;
}
void printQueue(ArrayQueue queue){
printf("<<< ");
int i = queue->front; //遍历队列需要从队首开始
do {
printf("%d ", queue->array[i]); //先打印当前位置上的元素
i = (i + 1) % queue->capacity; //然后 向后循环移动
} while (i != queue->rear); //当到达队尾时,结束
printf("<<<\n");
}
int pollQueue(ArrayQueue queue)
{
if(queue->rear==queue->front)
{
cout<<"队列为空!";
return 0;
}
int tmp=queue->array[queue->front];
queue->front=(queue->front + 1) % queue->capacity;
return tmp;
}
int main(){
struct Queue queue;
initQueue(&queue);
for (int i = 0; i < 5; ++i) {
offerQueue(&queue, i * 100);
}
printQueue(&queue);
pollQueue(&queue);
printQueue(&queue);
}
二. 队列–用链表实现
//单向链表实现队列
#include <bits/stdc++.h>
using namespace std;
typedef int E;
struct LNode {
E element;
struct LNode * next;
};
typedef struct LNode * Node;
struct Queue{
Node front, rear;
};
typedef struct Queue * LinkedQueue; //因为要存储首位两个指针,所以这里封装一个新的结构体吧
_Bool initQueue(LinkedQueue queue){
Node node = (Node)malloc(sizeof(struct LNode));
if(node == NULL) return 0;
node->next = NULL;
queue->front = queue->rear = node; //一开始两个指针都是指向头结点的,表示队列为空
return 1;
}
_Bool offerQueue(LinkedQueue queue, E element){
Node node = (Node)malloc(sizeof(struct LNode));
if(node == NULL) return 0;
node->next = NULL;
node->element = element;
queue->rear->next = node; //先让尾结点的下一个指向新的结点
queue->rear = node; //然后让队尾指针指向新的尾结点
return 1;
}
void printQueue(LinkedQueue queue){
printf("<<< ");
Node node = queue->front->next;
while (1) { //注意不能直接判空,因为前面我们没考虑,也就没将新结点next设定为NULL
printf("%d ", node->element);
if(node == queue->rear) break; //当已经打印最后一个元素后,再结束
else node = node->next;
}
printf("<<<\n");
}
E pollQueue(LinkedQueue queue){
E e = queue->front->next->element;
Node node = queue->front->next;
queue->front->next = queue->front->next->next; //直接让头结点指向下下个结点
if(queue->rear == node) queue->rear = queue->front; //如果队尾就是待出队的结点,那么队尾回到队首位置上
free(node); //释放内存
return e;
}
int main(){
struct Queue queue;
initQueue(&queue);
for (int i = 0; i < 5; ++i) {
offerQueue(&queue, i*100);
}
printQueue(&queue);
while (queue.front!=queue.rear){
printf("%d ", pollQueue(&queue));
}
}