经过我的调研,在网络上介绍的双端队列,大多要么是只介绍了概念,要么就直接介绍deque的操作,学校里的课程也基本跳过,没有对双端队列这个更好的数据结构的底层操作做出剖析,除非深入学习过STL源码,所以我就来啦~
目录
1双端队列的概念
❄️2双端队列(顺序结构)的操作
⚽3完整代码(C语言)
4deque
双端队列,故名思意,就是两端都可以当作队列:从左向右看是队列,从右向左看也是队列;
这就意味着
左边可以进行插入和删除,右边也可以进行插入和删除
这就推导出
可以实现左进左出、左进右出、右进右出、右进左出四种插入删除方式
总结一下
栈:左进左出、右进右出
队列:左进右出,右进左出
即双端队列可以同时实现栈和队列的功能,
显然是一种更为复杂的数据结构。
那么怎样实现这样的插入删除功能呢?
要自己想出在一个连续的空间内同时实现栈和队列的操作其实是挺费脑筋的,我就先直接给出了。
1.我们需要两个指针(left+right)
left:负责左进左出(左进:left--,左出:left++)
right:负责右进右出(右进right++,右出right--)
2.无论左进还是右进,第一个元素的插入都放在数组的第一个位置
我们来看看动态图吧!
栈-左进左出
栈-右进右出
队列-左进右出
队列-右进左出
看懂了插入和删除,我们就来看看完整代码吧!另外,双端队列的链式结构也是可以类比的嗷~
#include
#include
void Init();
int isEmpty();//队空
int isFull();//判断队满
void left_insert(int);//左边插入、left--
void right_insert(int);//右边插入、right++
void left_delete();//左边删除、left++
void right_delete();//右边删除、right--
/*全局变量*/
int* queue;//指针数组
int maxSize;//数组的容量
int size;//当前元素的个数
int left;//左指针,用于左进、左出
int right;//右指针,由于右进、右出
int main()
{
//左插右删 右插左删(队列) 左插左删 右插右删(栈)
Init();
right_insert(1);
right_insert(2);
left_insert(3);
left_delete();
left_delete();
right_delete();
}
void Init()
{
queue = (int*)malloc(5 * sizeof(int));
maxSize = 5;
size = 0;
}
int isEmpty()
{
if (size == 0)
{
return 1;
}
else
{
return 0;
}
}
int isFull()
{
if (size == maxSize)
{
return 1;
}
else
{
return 0;
}
}
void left_insert(int key)
{
if (isFull())
{
printf("队满\n");
}
else
{
//如果队列此时为空 插入第一个元素在第一个位置0处
if (isEmpty())
{
left = right = 0;
queue[left] = key;
}
//如果不是插入第一个元素,就要从最右边开始
//第一次插入后,指针仍指向0,需要移动到最右边,然后左指针左减
else
{
if (left == 0)
{
left = maxSize;
}
queue[--left] = key;
}
size++;
}
}
void right_insert(int key)
{
if (isFull())
{
printf("队满\n");
}
else
{
//如果队列此时为空 插入第一个元素在第一个位置0处
if (isEmpty())
{
left = right = 0;
queue[right] = key;
}
//如果不是插入第一个元素,就要从最第2个位置开始,然后右指针右移
//如果插入到最右边了,就代表插满了
else
{
if (right == maxSize - 1)
{
right = -1;
}
queue[++right] = key;
}
size++;
}
}
void left_delete()
{
if (isEmpty())
{
printf("队列空\n");
}
else
{
//如果删除到最右边元素了,就要再删除最后一个存放在位置0处的元素
if (left == maxSize - 1)
{
printf("此时删除的元素为%d", queue[left]);
left = 0;
size--;
}
//如果不是最右边的元素,左指针右移
else
{
printf("此时删除的元素为%d", queue[left]);
left++;
size--;
}
}
}
void right_delete()
{
if (isEmpty())
{
printf("队列空\n");
}
else
{
//如果删除到最左边元素了,删除后右指针又移动到最右边
if (right == 0)
{
printf("此时删除的元素为%d", queue[right]);
right = maxSize - 1;
size--;
}
//如果没有删除到最左边元素,右指针左移
else
{
printf("此时删除的元素为%d", queue[right]);
right--;
size--;
}
}
}
deque是C++中STL里的又一个顺序容器,我们之前介绍了vector和list,可以看看之前的介绍
图解双向链表(含完整C代码)+剖析STL顺序容器List(C++)https://blog.csdn.net/weixin_54186646/article/details/123596062?spm=1001.2014.3001.5501动态二维数组类(C++ Vector)https://blog.csdn.net/weixin_54186646/article/details/123442733?spm=1001.2014.3001.5501
我们之前说过,vector是我们顺序容器中的首要选择,除非我们有更好的理由选择其他的容器,那选择deque的更好理由是什么呢?
显而易见:deque不仅支持快速随机访问,在头尾插入和删除的效率都很高;不过若要在中间插入删除,那代价就很高了。
d.push_back(t); | 在d的尾部创建一个值为t的元素,返回void |
d.push_front(t); | 在d的头部创建一个值为t的元素,返回void |
pop_back(); | 删除一个d的尾部元素,返回void |
pop_front(); | 删除一个d的头部元素,返回void |
其他的操作基本上都是可以使用的,包括用下标访问元素d[i],访问头元素d.front(),尾元素d.back()。
那今天就先到这里啦,感谢你的大力支持!