上一篇文章中我们说到了循环队列,今天我们来说一说如何用链式结构来存储队列。
链队列
是不是感觉很熟悉,这分明就是单向链式表嘛。front指向队头,rear指向队尾,没毛病。 入队时,队尾追加新节点temp,rear指向新结点temp,新节点temp成队尾; 出队时,用一个临时结点delTemp暂存front指向结点,front指向delTemp的下一个结点,临时结点delTemp释放,也就是从当前队列中出队了。
注意:一定是要先把front指向一下一个结点,然后在释放,否则front可能就找不到下一个结点了呢。
来,闲话不多说,翠花,上酸菜……(代码来一波)
/* 定义链式队列*/
typedef struct QNode // 结点
{
ElementType data;
struct QNode *next;
}QNode;
// 链队列结构
typedef struct {
QNode *front; // 队头
QNode *rear; // 队尾
}linkQueue;
// 创建一个空队列
Status createLinkQueue(linkQueue *Q){
// 头指针,尾指针生成新节点
Q->front = Q->rear = malloc(sizeof(QNode));
// 判断创建结点是否成功
if (!Q->front) {
return ERROR;
}
return OK;
}
// 销毁队列,将队列的每个结点都释放,整个队列都没有了
Status destoryLinkQueue(linkQueue *Q){
// 遍历队列,释放每个结点
while (Q->front) {
// 用rear指向front的下一个指针
Q->rear = Q->front->next;
// 释放front指针
free(Q->front);
Q->front = Q->rear;
}
return OK;
}
// 清空队列,队列还是存在的,只是队列里面的内容清空了
Status clearLinkQueue(linkQueue *Q){
// 定义临时变量记录队头的位置
QNode *head = Q->front->next;
QNode *temp;
// 头结点是一个空结点
Q->rear = Q->front = NULL;
while (head) {
temp = head;
head = head->next;
free(temp);
}
return OK;
}
// 判断队列是否为空
Status isEmptyLinkQueue(linkQueue Q)
{
if (Q.front == Q.rear) {
return TRUE;
}
return FALSE;
}
// 判断队列的长度
int linkQueueLength(linkQueue Q){
// 因为有一个头结点,所以从0开始计算
int i = 0;
// 临时变量记录头结点
QNode *temp = Q.front;
while (Q.rear != temp) {
i ++;
temp = temp->next;
}
return i;
}
// 入队
Status inLinkQueue(linkQueue *Q, ElementType data)
{
//1. 创建一个新节点,数据为data
QNode *temp = (QNode *)malloc(sizeof(QNode));
// 创建不成功,返回ERROR
if (!temp) {
return ERROR;
}
temp->data = data;
temp->next = NULL;
// 将temp插入到队尾位置
Q->rear->next = temp;
// 移动rear指针指向最新结点
Q->rear = temp;
return OK;
}
// 出队
Status outLinkQueue(linkQueue *Q,ElementType *outData)
{
// 如果是空队列,返回error
if (isEmptyLinkQueue(*Q)) {
return ERROR;
}
// 记录出队的数据
QNode *delTemp = Q->front->next;
*outData = delTemp->data;
// 向后移动front指针
Q->front->next = delTemp->next;
// 删除的元素就是队尾元素,最后队列为空
if (Q->rear == delTemp) {
Q->rear = Q->front;
}
// 释放要删除的指针
free(delTemp);
return OK;
}
// 获取队头元素
Status getHead(linkQueue Q, ElementType *data){
if (isEmptyLinkQueue(Q)) {
return ERROR;
}
QNode *head = Q.front->next;
*data= head->data;
return OK;
}
Status printLinkQueue(linkQueue Q){
if (isEmptyLinkQueue(Q)) {
return ERROR;
}
QNode *head = Q.front->next;
while (head) {
printf("%d ",head->data);
head = head->next;
}
printf("\n");
return OK;
}
int main(int argc, const char * argv[]) {
// insert code here...
printf("链队列表示与操作实现\n");
linkQueue Q;
// 创建队列
if (createLinkQueue(&Q)) {
printf("成功构建了一个空队列\n\n");
}
printf("是否为空队列? %d (1:是 0:否)\n\n",isEmptyLinkQueue(Q));
//5.插入元素到队列中
inLinkQueue(&Q, -3);
inLinkQueue(&Q, 6);
inLinkQueue(&Q, 12);
printf("队列的长度为 %d\n\n",linkQueueLength(Q));
printf("是否为空队列? %d (1:是 0:否)\n\n",isEmptyLinkQueue(Q));
//6.遍历队列
printf("队列中的元素如下:\n");
// 打印队列
printLinkQueue(Q);
// 获取队头元素
ElementType headData;
if (getHead(Q, &headData)) {
printf("队头元素:%d\n",headData);
};
// 出队
ElementType outData;
if (outLinkQueue(&Q, &outData)) {
printf("出队元素 %d\n\n",outData);
}
if (getHead(Q, &headData)) {
printf("新的队头元素:%d\n",headData);
};
//10.清空队列
clearLinkQueue(&Q);
//11.销毁队列
destoryLinkQueue(&Q);
return 0;
}
运行结果如下