队列的链表实现和队列的数组实现相比区别还是很大的.
首先我们需要2个指针front
和rear
, 分别指向头节点和尾节点.
这两个指针不属于节点本身的数据, 因此我们把这个两个指针单独定义成一个结构体.
因此, 队列的链表实现一共需要2个结构体, 一个存储队列数据本身, 一个存储头和尾指针.
在createQueue()
初始化函数中, 让front
指针指向NULL
, 通过front指针已经足够
判断队列为空的情况, 注意这里不能初始化rear
指针也等于NULL
, 否则再指向入队操作
时就会出现问题.
在入队函数add()
中, 首先根据front
指针是否等于NULL
来判断队列是否是初次插入元素.
在出队函数del()
中, 先判断队列是否为空.
C语言完整代码实现如下:
#include <stdio.h>
#include <stdlib.h>
struct queue {
int data;
struct queue* next;
};
struct queuePointer {
struct queue* front;
struct queue* rear;
};
typedef struct queue node;
typedef struct queue* link;
typedef struct queuePointer pnode;
typedef struct queuePointer* pointer;
// 函数声明
pointer createQueue (pointer p);
void add (pointer p, int x);
int del (pointer p);
void print (pointer p);
int main () {
/* 简单测试开始 */
pointer qptr = createQueue(qptr);
add(qptr, 100);
add(qptr, 200);
add(qptr, 300);
printf("%d
", qptr->front->data); // 100
printf("%d
", qptr->rear->data); // 300
printf("%d
", del(qptr)); // 100
printf("%d
", qptr->rear->data); // 300
printf("
");
/* 简单测试结束 */
/*复杂测试开始*/
int i;
pointer qptr2 = createQueue(qptr);
for (i=2; i<=20; i+=2) {
add(qptr2, i);
}
print(qptr2);
del(qptr2);
del(qptr2);
del(qptr2);
print(qptr2);
/*复杂测试结束*/
/* 对头队尾指向同一个节点测试开始 */
pointer qptr3 = createQueue(qptr);
add(qptr3, 666);
del(qptr3);
add(qptr3, 999);
print(qptr3);
/* 对头队尾指向同一个节点测试结束 */
return 0;
}
// 创建空队列
pointer createQueue (pointer p) {
p = (pnode*)malloc(sizeof(pnode)); // 这步非常关键, 注意我们使用了嵌套结构体
p->front = (node*)malloc(sizeof(node));
p->rear = (node*)malloc(sizeof(node));
p->front = NULL;
return p;
}
// 入队
void add (pointer p, int x) {
link tmp = (node*)malloc(sizeof(node));
tmp->data = x;
tmp->next = NULL;
// 如果这时队列中只有一个元素
if (p->front == NULL) {
p->front = tmp;
}
p->rear->next = tmp;
p->rear = tmp;
}
// 出队
// 返回头结点元素的值
int del (pointer p) {
if (p->front == NULL) {
printf("队列元素为空, 无法出队
");
return 0; // 0表示错误信息
}
link tmp = p->front;
int tmpValue = p->front->data;
p->front = p->front->next;
free(tmp);
return tmpValue;
}
// 打印
void print (pointer p) {
int length = 0;
link head = p->front; // 不能直接修改p->front来遍历
if (head == NULL) {
printf("当前队列信息为空
");
} else {
printf("当前队列的信息如下:
");
while (head) {
printf("%d
", head->data);
head = head->next;
length++;
}
printf("p->front->data = %d
", p->front->data);
printf("p->rear->data = %d
", p->rear->data);
printf("队列的总长度为: %d
", length);
}
printf("
");
}