C语言实现单链队列的基本操作
前面实现了队列的顺序结构,这一篇我们来实现队列的链式结构。
首先说明要使用到的结构体,第一个结构体,struct qnode,它包含两个成员,一个是数据变量data,另外一个是指向下一个节点的指针*next。第二个结构体queue包含的成员是队列的头指针和尾指针,他们都是指向struct qnode的结构体指针。
下面说明需要编写的三个函数:初始化函数Sq_Init(),插入元素函数Enqueue(),删除元素函数Dequeue()。
第一个函数实现的功能是通过malloc函数,建立一个大小为sizeof(node)的栈区,我们将头指针以及尾指针都指向这个结构体变量,再将这个节点的指针域q->front->next指向null。
第二个函数,首先建立一个大小为sizeof(node)的结构体变量p,由于插入元素是在队尾进行,所以p.next指向null,同时我们对p的数据域p.data进行赋值。第二步,由于尾指针此时指向上一个节点,所以我们将尾指针所指向的节点的指针域t指向p,这样就将上一个节点指向了节点p,最后再将尾指针指向p。也就是说,尾指针始终指向最后一个节点,且尾指针本身并没有存放自身数据的内存,但是头指针有,我们的初始化函数就为头指针指定了一片区域,用来存放指针变量,它的数据域我们并没有使用。
第三个函数,首先检查队列有没有数据,如果没有就返回ERROR。在队列中删除元素是从头节点处开始,因此我们要将头指针指向的区域删除掉,这里我们用到一个指向结构体变量node的指针*p,我们通过头指针找到它后面的节点,改变头指针,使它指向下个节点所指向的下下个节点。此时,指针*p指向了下个节点,我们将下个节点存储的数据返回,这里使用的是指针变量的形参+普通变量的实参来完成。这里又加入了一个判断语句,if(p->next == null)用来判断队列是否空了,如果空了,尾指针在后面的free(p)后,会指向未知区域,为了避免这种情况,将尾指针指向头指针所在节点的区域。最后释放删除掉的元素所在的区域。
编译环境VC++6.0,下面是完整代码:
#include <stdio.h>
#include <stdlib.h>
#define SElemType int
#define STATUS int
#define ERROR 0
#define OK 1
#define null 0
#define TRUE 1
#define FALSE 0
#define QElemtype int
typedef struct qnode{
QElemtype data;
struct qnode *next;
}node;
typedef struct SqQueue{
node *front;
node *rear;
}queue;
STATUS Sq_Init(queue *q)
{
q->front = q->rear = (node *)malloc(sizeof(node));
if(q->front == null)return ERROR;
q->rear->next = null;
return OK;
}
STATUS Enqueue(queue *q,QElemtype e)
{
node *p;
p = (node *)malloc(sizeof(node));
if(p == null)return ERROR;
p->data = e;
p->next = null;
q->rear->next = p;
q->rear = p;
return OK;
}
STATUS Dequeue(queue *q,QElemtype *e)
{
node *p;
if(q->front == q->rear)return ERROR;
p = q->front->next;
q->front->next = p->next;
*e = p->data;
if(p->next == null)q->front = q->rear;
free(p);
return OK;
}
int main()
{
queue q;
node *p;
QElemtype e;
if(Sq_Init(&q))printf("initial OK!\n");
Enqueue(&q,1);
Enqueue(&q,2);
Enqueue(&q,3);
Enqueue(&q,4);
printf("队列内的元素:");
p = q.front->next;
while(p != null)
{
printf("%d ",p->data);
p = p->next;
}
Dequeue(&q,&e);
printf("删除的元素:%d\n",e);
return 0;
}
下面是运行结果: