什么是队列
1、先进先出的线性表
2、只在队头删除
3、在队尾插入
什么是链式队列
1、用链表表示的队列叫做链式队列
2、两个分别指向队头和队尾的指针
3、空的链队列的判断条件是队头和队尾指针同时指向头结点
链式队列的存储结构
typedef struct QNode {
QElemType data; //队列元素
struct QNode *next; //指向下一个元素节点
}QNode, *QueuePtr;
typedef struct {
QueuePtr front; //队头指针
QueuePtr rear; //队尾指针
}LinkQueue;
初始化
void InitQueue(LinkQueue &Q) {
QNode *QHead = (QNode*)malloc(sizeof(QNode));//构建头结点
Q.rear = Q.front = QHead; //初始化队头和队尾指针,指向头结点
Q.front->next = Q.rear->next = NULL;//在使用前把指针域设置为NULL
}
清空队列
只是清空队列
让队列重置成刚初始化的样子
void ClearQueue(LinkQueue &Q){
Q.rear = Q.front; //初始化为头尾都指向同一处
QueuePtr p,q;//设置变量来进行指针的移动
p = Q.front->next;//之后清空头结点后面节点的数据和指针域
Q.front->next = NULL;
while(p) {
q = p;
free(q);
p = p->next;//p指针进行更替滑动
}
}
销毁队列
使得队列不再存在
所以是需要free头结点的
void DestroyQueue(LinkQueue &Q) {
while (Q.front) {
Q.rear = Q.front->next; //让尾节点作为滑动的指针,从front开始往后清空
free(Q.front);
Q.front = Q.rear;
}
}
求队列长度
设置计时器
从头结点开始累加
头结点是没有存储数据的
所以计数器从1开始
如果计数器从0开始
p=Q.front;
int QueueLength(LinkQueue Q) {
QueuePtr p;
int i = 1;
p = Q.front->next;//从front开始
while (p != Q.rear) {
printf("data:%d\n", p->data);
i++;
p = p->next;
printf("i:%d\n", i);
}
return i;
}
在求队列长度时候,起初我的做法为下。其实是大错特错的
因为这里是链式存储的,不可以直接通过尾指针-头指针返回的是之间的地址差。
而为什么在栈中可以S.base-S.top
,因为栈是顺序存储的。top和base相当于栈的下标,地址是连续一片的。所以可以。
return Q.rear-Q.front
添加队列元素
void EnQueue(LinkQueue &Q,QElemType data) {
QueuePtr L = (QNode*)malloc(sizeof(QNode));//创建新节点
L->data = data;//把要插入的数据放进节点中
L->next = NULL;//因为在队尾插入,所以始终队尾的next为NULL
Q.rear->next = L;//把新节点放在当前队尾的后面
Q.rear = L;//然后更新队尾指针,指向新节点
//
}
空队列
队列为空的条件为头指针和尾指针都指向头结点
bool QueueEmpty(LinkQueue Q) {
if (Q.rear == Q.front)
return true;
return false;
}
获取队头元素
Status GetHead(LinkQueue Q,QElemType &elem){
elem = Q.front->next->data;
return elem;
}
删除队列元素
Status DeQueue(LinkQueue &Q) { //删除队头元素
if (Q.rear == Q.front)//如果队列为空
return -1;//结束
QueuePtr p;
//通过移动Q.front指针删除
//其实还存在
//只是不能再访问了
QElemType e;
p = Q.front->next;//使用p记录要被删除的节点
e = p->data;//把删除的节点的数据给e
Q.front->next = p->next;//把p后面的节点给头结点的后面
//如果队列的最后一个元素被删除了,要让尾指针重新指向头结点
if (Q.rear == p) {
//就要让尾指针重新等于头指针
Q.rear = Q.front;//如果只有一个元素,然后被删除了
}
free(p);//最后free那个被删除的节点
return e;
}
遍历队列
void visit(QElemType elem) {
printf("%d\t", elem);
}
Status QueueTraverse(LinkQueue Q, void(visit)(QElemType)) {
printf("队列的所有元素:\n");
if (Q.rear == Q.front)return -1;//为空时,结束函数
QueuePtr p = Q.front->next;//用变量记录队头,进行指针滑动遍历
while(p) {
visit(p->data);
p = p->next;//更替p指针
}
return 1;
}