Java数据结构--双端队列

一:定义

  • 双端队列是一种具有队列和栈性质的数据结构,即可在线性表的两端进行插入和删除等操作

49ec4ccacad546c5bf702a6c6e683d75.jpg

二:.Java API中的Deque

知道了双端队列的定义,下面我们来了解一下Java API中的Deque类,知道双端队列是如何创建以及使用的

1.与栈以及队列的联系

7027bccff5694d9186c2001dbd5aebe1.jpg

从中我们可以知道,双端队列完全可以当做栈以及队列使用,栈以及队列中的增删查等方法在双端队列中均有方法与之对应实现

2.增删查等方法摘要

64476238e02a486888783c2cfe739d9a.jpg

 4ea5b2a32b0546578b7b8a2ac1ee878c.jpg

 27cf6bbc579c4544b8578cc26672a8c9.jpg

 a9fd62db3e9e4f838269b68a54a0d10d.jpg

 3.双端队列的创建以及使用

79626797cbd04fffb1edf6551a18efe3.png

 可以看到Deque类是一个接口,实现一个接口我们要重写接口中的所有方法。但Deque同时也实现了LinkedList类,因此创建Deque类我们可以new LinkedList类。

我们知道了Deque类中的一些方法,下面我们就来创建一个双端队列,知道其是如何创建使用的吧

bf5c0e04ba9f42efbbe0a2f7bda7a5b8.jpg

 3112fda874b44c33aca15678b390165f.jpg

三:代码实现

知道了如何使用双端队列,下面我们就来实现一下其中的各个方法吧。下面将基于链表以及数组来分别实现

⑴基于链表

双端队列的添加方法(头部,尾部),我们需要知道要插入位置的头节点以及尾节点,因此使用双向环形链表实现要方便许多

如图所示便为一个双向循环链表

536c0d0da8bd4f188967ca22149766bd.jpg

1.节点的创建

创建一个双向循环链表节点,我们需要一个指向前一个节点的指针(pre)以及指向后面节点的指针( next)

ae26e4d684134cbc989fbe2f32d55fcd.jpg

 2.双端队列的创建

我们需要一个头部哨兵节点sentinel,方便我们获取队首元素(sentinel.next)以及队尾元素(sentinel. pre)

19f6567ff5364dd8a47c7477b4e3a2c2.jpg

 3. addFirst 将指定元素插入此双端队列的开头

7379f5d0456d4e6f83ca7b1609c27441.jpg 

思路:向队列头部添加元素,首先我们需要获取哨兵节点sentinel以及头部节点( sentinel.next),再创建一个新节点,更新对应的指针即可 864fc0058d7643bfa8831f61b392ff0f.png

 4. addLast 将指定元素插入此双端队列的尾部

f0c56e3a94d04e9c923e14b8a9ffe3f2.jpg 

思路:向队列尾部添加元素,首先我们需要获取哨兵节点sentinel以及尾部节点( sentinel.pre),再创建一个新节点,更新对应的指针即可 

d8074e383bfc4727ba4be7f7ce3dab7c.jpg

5. pollFirst 获取并移除此双端队列的第一个元素

3aefd8bfbfc84c6c9877cf78525c2637.jpg

思路:首先要获取哨兵节点(sentinel)以及头部节点的下一个节点( sentinel.next.next),最后更新对应的指针即可

3b60ffe8eb754e5bb235224699005c46.jpg

6.pollLast 获取并移除此双端队列的最后一个元素

0d0a3ddfa9bc40ddaa7c9786ff759e5f.jpg

 思路:首先获取尾部节点的前一个节点( sentinel. pre.pre)以及哨兵节点( sentinel),最后更新相应指针即可

d34783fab30b40408c74a21ec817f4e9.png

7. peekFirst 获取,但不移除此双端队列的第一个元素

思路:直接返回队首元素( sentinel.next.val)

peekLast 获取,但不移除此双端队列的最后一个元素

思路:直接返回队尾元素( sentinel.pre.val)

b5520592a8f04d9186a5a9fa9dec1ef9.png

⑵基于数组

在一个数组中进行添加删除操作是比较麻烦的。还记得我们在队列的数组实现中,有一种循环数组,可以很方便的完成添加以及删除等操作

1.双端队列的创建

基于循环数组,那我们就需要一个头指针( head)以及尾指针( tail),其中尾指针( tail)指向的位置并不插入元素,也就是下一次尾补要插入的位置。我们初始化数组arr的容量为10,head=tail=0

f44c81c824ea469cb38da9f1b857be1d.png

 2. isFull 判断队列是否存满

首先我们要知道循环数组的指针head以及tail,大小不同判断也不同

①当head<tail时

27c6cbb790994747a425ab8f1d4bd643.jpg

②当head>tail时

a48302ab28dd45c4abe8fe0c345975df.jpg

087a628e7f104c2ebf792a22082eda64.png

3.指针的移动

在循环数组实现的队列中,我们移动头尾指针时,使用的是取模的方法。下面我们来使用一种新的方法来获取移动的指针

移动时,超出边界,获取的指针会不同

①向右移动

Ⅰ.未超出右边界,传入的位置+1

Ⅱ.超出右边界时,传入的位置=0即可(进行循环)

cc6779109aaf4abd8c88d5ac994bd80c.jpg

②向左移动

Ⅰ.未超出左边界时,传入的位置-1

Ⅱ.超出左边界时,传入的位置=数组最后一位索引

22079108e5d344159fbdf47c4e05ee11.jpg

37576e0683124b779678c9f6b47b0c55.png

 4. offerFirst 将指定元素插入此双端队列的开头

思路: head指针前移,在head位置传入要插入的元素

b9f9d258147943118bf396051685d069.jpg

5. offerLast 将指定元素插入此双端队列的末尾

思路:在tail位置传入要插入的元素,再更新tail指针

df9dd0a6a63f40859c09774cb1c24815.jpg

6. pollFirst 获取并移除此双端队列的第一个元素

思路:将head位置的空间置空,更新head指针右移

4fd2e48b71e54350932c84b46b39f76c.jpg

7. pollLast 获取并移除此双端队列的最后一个元素

思路:向左移动tail指针,将tail位置的空间置空

e0698c5d9b594ce0a253c14c99a3c7f0.jpg

8.peekFirst 获取,但不移除此双端队列的第一个元素

思路:直接返回head位置元素

peekLast 获取,但不移除此双端队列的最后一个元素

思路:直接返回tail位置元素

e96549c937f245139c9d17f8a576599d.png

四:结果显示

各种方法都写出来了吗?下面我来带入数据爽一下吧

1.基于链表

c52221120af643aea3ae63a4e2e1667c.jpg

 d5e8ac062d0b4ecebd2eb93f6992f410.jpg

 2.基于数组

a8702a083bda4fe8b199a36b69c042f0.jpg

d828a4ab49a6424bbcfd02b53ac671be.jpg 

 若存在错误,不足之处,望各位指出更正₍˄·͈༝·͈˄*₎◞ ̑̑

 

 

 

 

 

 

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

汤姆大聪明

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值