赞
踩
本篇进行队列的学习。使用C语言实现
排队是体现了“先来先服务”的原则。
在多道程序运行的计算机系统中,可以同时有多个作业运行,他们的运算结果都需要通过通道输出,若通道输入未完成,后来的作业应该排队等待,每当通道输入完成时,则从队列的对头退出作业进行输出操作。凡是申请该通道输出的作业都从队尾进行等待。
队列是另一种限定性的线性表,它只允许插入在表的一端进行,删除在表的另一端进行。允许插入的一端叫做队尾,允许删除的一端叫做队头。队列的插入操作通常称为“入队”或“进队”,而队列的删除操作称为“出队”或“退队”
当队列中无数据时,称为“空队列”
队头元素总是最先进队列,也总是最先出队列,这种表是按照“先进先出”原则组织数据的。因此队列也被称为“先进先出”表
如图,入队的顺序为0,1,2,3,…,n-1,则队头元素为0,队尾元素为n-1,出队顺序仍是0,1,2,3,…,n-1。
与线性表,栈类似,队列也有顺序存储和链式存储两种存储方法。队列的顺序存储结构可以简称“顺序队列“
顺序队列师指利用一组地址连续的存储单元一次存放队列中的数据元素
使用一维数组来作为队列的顺序存储空间,另外在设置两个指示器,一个为指向队头元素的指示器front,另一个为指向队尾元素的指示器rear
在C语言中,数组的下标是从0开始的,因此为了算法设计的方便,约定在初始化队列时,空队列的front = rear = -1
还约定在非空队列中,头指示器front总是指向队列中实际队头元素的前一个位置。尾指示器rear总是指向队尾元素。
typedef int ElemType; #define MAXSIZE 50 typedef struct{ ElemType elem[MAXSIZE]; int rear; int front; } SeQueue; int main(int argc, const char * argv[]) { //定义一个指向队列的指针 SeQueue* sq; //申请一个顺序队列的存储空间 sq = (SeQueue*)malloc(sizeof(SeQueue)); return 0; }
//入队时尾指针+1的操作
sq->rear = (sq->rear+1)%MAXSIZE;
//出队时队头指针+1的操作尾
sq->rear = (sq->front+1)%MAXSIZE;
typedef int ElemType; #define MAXSIZE 50 typedef struct{ ElemType elem[MAXSIZE]; int rear; int front; } SeQueue; //置空队列 SeQueue* InitSeQueue(){ q = (SeQueue*)malloc(sizeof(SeQueue)); q->front = q->rear = MAXSIZE - 1; return q; } //入队 int InSeQueue(SeQueue* q,ElemType x){ if ((q->rear+1)%MAXSIZE == q->front){ return FALSE; }else{ q->rear = (q->rear+1)%MAXSIZE; q->elem[q->rear] = x; return TRUE; } } //出队 int OutSeQueue(SeQueue* q,ElemType* x){ if (q->front == q->rear){ return FALSE; }else{ q->front = (q->front + 1)%MAXSIZE; *x = q->elem[q->front]; return TRUE; } } //判空队列 int EmptySeQueue(SeQueue* q){ if (q->front == q->rear){ return TRUE; }else{ return FALSE; } }
在程序设计语言中不可能动态分配一维数组来实现循环队列。如果要使用循环队列,则必须为它分配最大长度的空间,若用户无法预计所需队列的最大空间,则可以采用链式结构来存储队列,链式存储结构称为“链队列”,和链栈类似,可以使用单链表来实现链队列。根据队列FIFO原则,链队列中为了操作方便,可以采用带头结点的单链表表示队列,并设置一个队头指针front和一个队尾指针rear。头结点始终指向头结点,尾直接指向当前最后一个元素的结点。
链队列的数据类型描述如下:
typedef struct{
ElemType data;
struct node* next;
} QNode;
typedef struct{
QNode* front;
QNode* rear;
} LQNode;
建立带头结点的链队列:
链队列的各种操作的实现也和单链表类似,只是限定插入操作在表尾进行,删除操作在表头进行。它的插入和删除是单链表的特殊情况,
在链队列的删除操作中,如果仅有一个元素结点,删除后还需要修改尾指针。
//创建一个带头结点的空队 LQueue* Init_LQueue(){ LQueue* q; QNode* p; q = (LQNode*)malloc(sizeof(LQNode)); p = (QNode*)malloc(sizeof(QNode)); p->next = NULL; q->front = q->rear = p; return q; } //入队 void InLQueue(LQueue* q,DataType* x){ QNode* p; p = (QNode*)malloc(sizeof(QNode)); p->data = x; p->next = NULL; q->rear->next = p; q->rear = p; } //队判空 int Empty_LQueue(LQueue* q){ if (q->front == q->rear){ return 0; } else{ return TRUE; } } //出队 int Out_LQueue(LQueue* q,DataType* x){ QNode* p; if (Empty_LQueue(q)){ return FALSE; } else{ p = q->front->next; q->front->next = p->next; *x = p->data; free(p); if (q->front->next == NULL){ q->rear = q->front; } } return TRUE; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。