今天写链队列的相关代码,一共分为两个部分,第一部分是带头结点的链队列,第二部分就是不带头结点的链队列。
带头结点的链队列
需要注意的点:
- 在这里,我们需要注意的是,出队的时候,我们需要判断,我们要删除的是不是队列中的最后一个,如果是,我们需要将rear指针指向头结点,来使得队列为空队列。
- 剩下就是要注意队列为空的条件了,这块在2019年的时候考过题目。
- 链队列其实是一个同时具备队头指针和队尾指针的单列表,这也是链队列不需要判断为满的理由。
代码如下:
//
// LinkQueue1.cpp
// Third
//
// Created by Jeffery on 2024/4/1.
// 带头结点的
#include <stdio.h>
#include <iostream>
typedef int ElemType;
using namespace std;
typedef struct LinkNode{
ElemType data;
struct LinkNode *next;
}LinkNode;
typedef struct {
LinkNode* front;
LinkNode* rear;
int length;
}LinkQueue;
// 初始化
void InitQueue(LinkQueue &Q){
Q.rear = Q.front = (LinkNode*)malloc(sizeof(LinkNode));
Q.front->next = NULL;
Q.length = 0;
}
// 判断队列是否为空
bool IsEmpty(LinkQueue Q){
if (Q.rear == Q.front) return true;
else return false;
}
// 入队操作
void InQueue(LinkQueue &Q, ElemType x){
LinkNode* s = (LinkNode*)malloc(sizeof(LinkNode));
s->data = x;
s->next = NULL;
Q.rear->next = s;
Q.rear = s;
Q.length ++;
}
// 出队操作
bool OutQueue(LinkQueue &Q, ElemType &x){
if (IsEmpty(Q)) return false;
// if (Q.rear == Q.front) return false; // 二者选一种即可
LinkNode* p = Q.front->next;
x = p->data;
Q.front->next = p->next;
if (Q.rear == p){
Q.rear = Q.front;
}
free(p);
Q.length --;
return true;
}
// 获取队头元素
void GetFrontElem(LinkQueue Q){
printf("队头元素是:%d\n", Q.front->next->data);
}
// 打印出现在队列里面的元素(不建议)
void PrintQueue(LinkQueue Q){
LinkNode* q = Q.front->next;
while (q != NULL){
printf("%d,", q->data);
q = q->next;
}
printf("\nlength = %d\n", Q.length);
}
int main(int argc, const char * argv[]) {
LinkQueue Q;
InitQueue(Q);
int x;
InQueue(Q, 1);
InQueue(Q, 2);
GetFrontElem(Q); // 队头元素是:1
InQueue(Q, 3);
InQueue(Q, 4);
InQueue(Q, 5);
PrintQueue(Q);
//1,2,3,4,5,
// length = 5
OutQueue(Q, x);
OutQueue(Q, x);
GetFrontElem(Q); // 队头元素是:3
OutQueue(Q, x);
OutQueue(Q, x);
PrintQueue(Q);
return 0;
}
不带头结点的链队列
需要注意的点:
- 我们需要注意
入队操作
,我们需要判断一下,是否现在是第一个入队的元素,如果是,我们需要单独讨论。
if (Q.front == NULL){
Q.front = s;
Q.rear = s;
}
而一般情况则是:
Q.rear->next = s;
Q.rear = s;
- 我们还需要注意
出队操作
,我们需要判断一下,现在出队的是不是我们队列的最后一个元素,如果是,则需要把rear
和front
都设置为NULL
.
代码如下:
//
// LinkQueue1.cpp
// Third
//
// Created by Jeffery on 2024/4/1.
// 不带头结点的
#include <stdio.h>
#include <iostream>
typedef int ElemType;
using namespace std;
typedef struct LinkNode{
ElemType data;
struct LinkNode* next;
}LinkNode;
typedef struct {
LinkNode* front;
LinkNode* rear;
int length; // 记录队列长度
}LinkQueue;
// 初始化
void InitQueue(LinkQueue &Q){
Q.rear = NULL;
Q.front = NULL;
Q.length = 0;
}
// 判断队列是否为空
bool IsEmpty(LinkQueue Q){
// 这里写下面这种写法也可以
//if (Q.rear == NULL) return true;
if (Q.front == NULL) return true;
else return false;
}
// 入队操作
void InQueue(LinkQueue &Q, ElemType x){
LinkNode* s = (LinkNode*)malloc(sizeof(LinkNode));
s->data = x;
s->next = NULL;
// 证明是插第一个的节点
if (Q.front == NULL){
Q.front = s;
Q.rear = s;
}
//其他情况
else{
Q.rear->next = s;
Q.rear = s;
}
Q.length ++;
}
// 出队操作
bool OutQueue(LinkQueue &Q, ElemType &x){
if(IsEmpty(Q)) return false;
// if(Q.rear == NULL) return false; //也行
LinkNode* p = Q.front;
x = p->data;
Q.front = p->next;
// 要出队的是队列的最后一个节点
if (Q.rear == p){
Q.rear = NULL;
Q.front = NULL;
}
Q.length --;
free(p);
return true;
}
// 获取队头元素
void GetFrontElem(LinkQueue Q){
printf("队头元素是:%d\n", Q.front->data);
}
// 打印出现在队列里面的元素(不建议)
void PrintQueue(LinkQueue Q){
LinkNode* q = Q.front;
while (q != NULL){
printf("%d,", q->data);
q = q->next;
}
printf("\nlength = %d\n", Q.length);
}
int main(int argc, const char * argv[]) {
LinkQueue Q;
InitQueue(Q);
int x;
InQueue(Q, 1);
InQueue(Q, 2);
GetFrontElem(Q); // 队头元素是:1
InQueue(Q, 3);
InQueue(Q, 4);
InQueue(Q, 5);
PrintQueue(Q);
// 1,2,3,4,5,
// length = 5
OutQueue(Q,x);
OutQueue(Q,x);
OutQueue(Q,x);
OutQueue(Q,x);
PrintQueue(Q);
return 0;
}
自己写的代码,欢迎指正.