单链队列操作
单链队列和单链表很相似。除了单链表具有的一些特性,单链队列还有两个分别指向队头和队尾的指针,就像是多了一种访问手段的单链表。(个人认为)
利用单链队列进行操作前,除了要声明链表节点信息的结构体,成员为数据域和指针域,还要要声明一个代表队列信息的结构体,成员为队头指针和队尾指针。为了操作方便,也给单链队列添加了一个头结点。空的单链队列的判决条件为队头指针和队尾指针均指向头结点。
目录
头文件定义
#ifndef _LinkQUEUE_H_
#define _LinkQUEUE_H_
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define SUCCESS 10000
#define FAILURE 10001
#define TRUE 10002
#define FALSE 10003
typedef int ElemType;
//单链队列节点信息
struct qnode
{
ElemType data;
struct qnode *next;
};
typedef struct qnode QNode;
//单链队列信息
struct linkqueue
{
QNode *front;
QNode *rear;
};
typedef struct linkqueue LinkQueue;
int QueueInit( LinkQueue **Q); //队列初始化
int QueueEmpty( LinkQueue *Q); //队列判空
int EnterQueue( LinkQueue *Q, ElemType e); //队列入队
int QueueLength( LinkQueue *Q); //队列求长
int GetFront( LinkQueue *Q); //获取队头数据
int DeleteQueue( LinkQueue *Q); //队列出队
int QueueClear( LinkQueue *Q); //队列重置
#endif
单链队列初始化
单链队列的初始化要做的工作,一是要给队列分配空间,二是要给队列内的头结点分配空间,并且对头结点,队头指针,队尾指针作初始化操作。
//队列初始化
int QueueInit( LinkQueue **Q)
{
if ( NULL == Q) //入参判断,确保传进来的地址有效
{
return FAILURE;
}
(*Q) = (LinkQueue *)malloc(sizeof(LinkQueue)); //给队列分配空间
if ( NULL == (*Q))
{
return FAILURE;
}
QNode *pHeadNode = (QNode *) malloc(sizeof(QNode)); //给头结点分配空间
if ( NULL == pHeadNode)
{
return FAILURE;
}
pHeadNode->next = NULL; //初始化头结点
(*Q)->front = pHeadNode; //初始化队头指针
(*Q)->rear = pHeadNode; //初始化队尾指针
return SUCCESS;
}
单链队列判空
单链队列是为空的判决条件为为队头指针和队尾指针均指向头结点。
//队列判空
int QueueEmpty( LinkQueue *Q)
{
if ( NULL == Q)//入参判断,队列存在
{
return FAILURE;
}
if (Q->rear == Q->front) //如果队尾指针指向头结点,则队列为空
{
return TRUE;
}
return FALSE;
}
单链队列入队
单链队列的入队,首先要定义一个新的节点来存值,再把新节点接到队尾。注意更新队尾指针。
//队列入队
int EnterQueue( LinkQueue *Q, ElemType e)
{
if ( NULL == Q ) //入参判断,队列存在
{
return FAILURE;
}
QNode *pNewNode = (QNode *)malloc(sizeof(QNode) * 1);//定义新节点并分配空间
if ( NULL == pNewNode)//如果分配失败返回FAILURE
{
return FAILURE;
}
pNewNode->data = e; //新节点数据域
pNewNode->next = NULL; //新节点指针域
Q->rear->next = pNewNode; //向队尾添加新节点
Q->rear = pNewNode; //更新队尾指针
return SUCCESS;
}
单链队列求长
单链队列求长,只要让一个指针从队头遍历到队尾,同时计数即可。
//队列求长
int QueueLength( LinkQueue *Q)
{
if ( NULL == Q) //入参判断,队列存在
{
return FAILURE;
}
int length = 0;
QNode *pNode = Q->front;
while (pNode != Q->rear)
{
pNode = pNode->next;
length++;
}
return length;
}
单链队列获取队头数据
单链队列的队头应该是,队头指针指向的头结点的下一个节点。
//返回队头数据
int GetFront( LinkQueue *Q)
{
if ( NULL == Q || Q->front == Q->rear) //入参判断,队列存在且非空
{
return FAILURE;
}
return Q->front->next->data; //返回队头数据
//队头应该是队头指针指向的头结点的下一个节点
}
单链队列出队
单链队列出队操作,需要用一个指针记录队头节点(队头指针front所指向的头结点的下一个节点),然后让front所指向的头结点的指针域指向队头节点的下一个节点来让队头节点出队。然后free释放队头节点所占用的空间。要注意的是在释放最后一个节点的时候,要调整队尾指针rear的位置,rear应该指向头结点。
//队列出队
int DeleteQueue( LinkQueue *Q)
{
if ( NULL == Q || Q->rear == Q->front) //入参判断,队列存在且非空
{
return FAILURE;
}
QNode *pNode = Q->front->next; //定义一个指针记录要出队的队头节点
if( NULL == pNode->next) //处理队尾指针
{
Q->rear = Q->front;
}
Q->front->next = pNode->next; //出队操作
free(pNode); //释放已经出队的节点的空间
pNode = NULL;
return SUCCESS;
}
单链队列重置
单链队列重置就是不断地出队,直到队列为空。
//队列清空
int QueueClear( LinkQueue *Q)
{
if ( NULL == Q) //入参判断
{
return FAILURE;
}
QNode *pNode = Q->front->next; //定义一个指针记录要出队的队头节点
while ( Q->rear != Q->front) //队列变成空队列的时候循环结束
{
if( NULL == pNode->next) //处理队尾指针
{
Q->rear = Q->front;
}
Q->front->next = pNode->next; //出队操作
free(pNode); //释放已经出队的节点的空间
pNode = Q->front->next; //继续让pNode指向下一个要出队的节点
}
return SUCCESS;
}
测试文件
#include "LinkQueue.h"
int main()
{
LinkQueue *Queue;
int ret = 0, i = 0 ;
ElemType e = 0;
srand( time(NULL) );
ret = QueueInit(&Queue); //单链队列初始化
if ( FAILURE == ret)
{
printf("Init failure.\n");
}
else if ( SUCCESS == ret)
{
printf("Init success.\n");
}
ret = QueueEmpty(Queue); //单链队列判空
if ( FALSE == ret)
{
printf("Queue is not Empty.\n");
}
else if ( TRUE == ret)
{
printf("Queue is Empty.\n");
}
for (i = 0; i < 11; i++)
{
e = rand() % 20;
ret = EnterQueue(Queue, e); //单链队列入队
if (FAILURE == ret)
{
printf("Enter %2d failure.\n", e);
}
else if (SUCCESS == ret)
{
printf("Enter %2d success.\n", e);
}
}
ret = GetFront(Queue); //单链队列获取队头元素
if ( FAILURE == ret)
{
printf("Get front elem failure.\n");
}
else
{
printf("front = %d\n", ret);
}
ret = DeleteQueue(Queue); //单链队列出队
if ( FAILURE == ret)
{
printf("Delete failure.\n");
}
else
{
printf("Delete success.\n");
}
ret = GetFront(Queue); //单链队列获取队头元素
if ( FAILURE == ret)
{
printf("Get front elem failure.\n");
}
else
{
printf("front = %d\n", ret);
}
ret = QueueLength( Queue); //单链队列求队长
if ( FAILURE == ret)
{
printf("Length failure.\n");
}
else
{
printf("Length = %d\n", ret);
}
ret = QueueClear( Queue); //单链队列重置
if ( FAILURE == ret)
{
printf("Clear failure.\n");
}
else if ( SUCCESS == ret)
{
printf("Clear success.\n");
}
ret = QueueEmpty(Queue); //单链队列判空
if ( FALSE == ret)
{
printf("Queue is not Empty.\n");
}
else if ( TRUE == ret)
{
printf("Queue is Empty.\n");
}
return 0;
}