1.队列的基本定义
队列是一种只能在队头进行删除在队尾进行添加的数据结构,基本的形式如下图,在头指针处可删除,在尾指针处可添加
![](https://img-blog.csdnimg.cn/img_convert/945f0507d583584c7ac4ca9f83888f99.png)
2.存在的问题
在c/c++中使用malloc分配的空间大小是固定的
在增加和删除的过曾中不断的有空间被废弃,线性表的基地址不断移动,造成很大的空间浪费
如图
![](https://img-blog.csdnimg.cn/img_convert/306be79c09a8f5cafa8abe46455f6b2f.png)
3.解决之道
因此出现了另一种结构来解决这个问题
循环结构(如图),即数据空间构成一个环,使得删改不断在这个环中进行,这样完美的解决了空间浪费等问题
![](https://img-blog.csdnimg.cn/img_convert/d8388a4ead0b19aa9df6090545982b25.png)
4队列的代码实现
- 链队列(由链表生成的队列)
基本结构(结点定义)
typedef struct Node
{
int data;
struct Node* next;
}dnode,*dLinkNode;
链栈的存储(实际上就存储指向头结点和尾结点的指针)
typedef struct {
dLinkNode front, rear; // 队头指针、队尾指针
}* LinkQueue,queue;
初始化(为链表分配空间)
LinkQueue crease() //创建队列并初始化(即创建第一个结点并给头指针尾指针赋空间并初始化)
{
dLinkNode L;
L = (dLinkNode)malloc(sizeof(dnode));
L->next = L; //创建头结点初始化(由于是循环所以指向自身)
LinkQueue F;
F = (LinkQueue)malloc(sizeof(queue));
F->front = L;
F->rear = L; //创建头指针尾指针初始化
return F;
}
入队(类似于链表的尾插法)
void qinsert(LinkQueue L,int n) //入队(类似于尾插法)
{
int x;
cin >> x;
(L->front)->data = x; //循环链表我们就不设置一个空的头结点了
for (int k = 1; k < n; k++)
{
dLinkNode H;
H = (dLinkNode)malloc(sizeof(dnode));
cin >> x;
H->data = x;
L->rear->next = H;
H->next = L->front;
L->rear = H;
}
}
出队
我们使用一个vector对象来存储对列中的元素
vector<int> out(LinkQueue L,int n) //出队(用vector来保存出队的数据)
{
vector<int>arr(n);
for (int i = 1; i <= n; i++)
{
if (L->front == L->rear)
{
cout << "error" << endl;
break;
}
arr[(i - 1)] = L->front->data;
L->rear->next = L->front->next;
L->front = L->front->next; //更新队头指针指向的位置
}
return arr;
}
打印(实际上即遍历队列)
void Print(LinkQueue L)
{
dLinkNode H;
H = L->front;
while (H!= L->rear)
{
cout << H->data << ',';
H = H->next;
}
cout << H->data << endl;
}
5.完整代码
#include<iostream>
#include<stdio.h>
#include<vector>
using namespace std;
typedef struct Node
{
int data;
struct Node* next;
}dnode,*dLinkNode;
typedef struct {
dLinkNode front, rear; // 队头指针、队尾指针
}* LinkQueue,queue;
LinkQueue crease() //创建队列并初始化(即创建第一个结点并给头指针尾指针赋空间并初始化)
{
dLinkNode L;
L = (dLinkNode)malloc(sizeof(dnode));
L->next = L; //创建头结点初始化(由于是循环所以指向自身)
LinkQueue F;
F = (LinkQueue)malloc(sizeof(queue));
F->front = L;
F->rear = L; //创建头指针尾指针初始化
return F;
}
void qinsert(LinkQueue L,int n) //入队(类似于尾插法)
{
int x;
cin >> x;
(L->front)->data = x; //循环链表我们就不设置一个空的头结点了
for (int k = 1; k < n; k++)
{
dLinkNode H;
H = (dLinkNode)malloc(sizeof(dnode));
cin >> x;
H->data = x;
L->rear->next = H;
H->next = L->front;
L->rear = H;
}
}
vector<int> out(LinkQueue L,int n) //出队(用vector来保存出队的数据)
{
vector<int>arr(n);
for (int i = 1; i <= n; i++)
{
if (L->front == L->rear)
{
cout << "error" << endl;
break;
}
arr[(i - 1)] = L->front->data;
L->rear->next = L->front->next;
L->front = L->front->next; //更新队头指针指向的位置
}
return arr;
}
void Print(LinkQueue L)
{
dLinkNode H;
H = L->front;
while (H!= L->rear)
{
cout << H->data << ',';
H = H->next;
}
cout << H->data << endl;
}
int main()
{
int n = 5;
vector<int>arr(n);
LinkQueue L;
L = crease();
qinsert(L, 10); //用1,2,3,4,5,6,7,8,9,10测试
Print(L);
arr=out(L, n);
for (int k = 0; k < n; k++)
cout << arr[k] << ' ';
cout << endl;
Print(L);
}
6.运行结果
![](https://img-blog.csdnimg.cn/img_convert/be032f94eefab3063a26061ecd71e569.png)