返回
前中后队列的魅力:链表实现的奥秘
前端
2023-11-23 16:06:15
算法解锁:前中后队列的设计与实现
前言
算法之旅的序幕就此拉开,欢迎踏入 LeetCode 的题海之滨。作为本次旅程的开篇,我们聚焦于一道看似简单却暗藏玄机的问题——设计前中后队列。它将考验我们对链表结构和算法策略的掌握程度。
1. 前中后队列的定义
前中后队列是一种特殊的数据结构,它包含三个队列:前队列、中队列和后队列。每个队列遵循先进先出的原则(FIFO)。前中后队列的核心特性如下:
- 前队列: 从队首插入元素,从队首删除元素。
- 中队列: 从队首插入元素,从队尾删除元素。
- 后队列: 从队尾插入元素,从队尾删除元素。
2. 链表实现
为了构建前中后队列,链表是一种理想的数据结构。链表是一种线性数据结构,由一系列相互连接的节点组成,每个节点包含一个数据域和一个指向下一个节点的指针。
链表节点结构:
class Node {
int data;
Node next;
}
前中后队列实现:
class FrontMiddleBackQueue {
private Node frontHead, middleHead, backHead, middleTail;
public FrontMiddleBackQueue() {
frontHead = middleHead = backHead = middleTail = null;
}
public void pushFront(int val) {
Node newNode = new Node(val);
newNode.next = frontHead;
frontHead = newNode;
updateMiddleHead();
}
public void pushMiddle(int val) {
Node newNode = new Node(val);
if (middleHead == null) {
middleHead = middleTail = newNode;
} else {
middleTail.next = newNode;
middleTail = newNode;
}
}
public void pushBack(int val) {
Node newNode = new Node(val);
if (backHead == null) {
backHead = newNode;
} else {
backHead.next = newNode;
}
backHead = newNode;
updateMiddleTail();
}
public int popFront() {
if (frontHead == null) {
return -1;
}
int val = frontHead.data;
frontHead = frontHead.next;
updateMiddleHead();
return val;
}
public int popMiddle() {
if (middleHead == null) {
return -1;
}
int val = middleHead.data;
if (middleHead == middleTail) {
middleHead = middleTail = null;
} else {
middleHead = middleHead.next;
updateMiddleTail();
}
return val;
}
public int popBack() {
if (backHead == null) {
return -1;
}
int val = backHead.data;
if (backHead == frontHead) {
frontHead = middleHead = backHead = null;
} else {
Node prev = getPrevNode(backHead);
prev.next = null;
backHead = prev;
}
return val;
}
private void updateMiddleHead() {
middleHead = frontHead;
int count = 1;
while (count < middleIndex()) {
middleHead = middleHead.next;
count++;
}
}
private void updateMiddleTail() {
middleTail = backHead;
int count = 0;
while (count < middleIndex()) {
middleTail = middleTail.next;
count++;
}
}
private Node getPrevNode(Node node) {
Node prev = null;
Node cur = frontHead;
while (cur != null && cur != node) {
prev = cur;
cur = cur.next;
}
return prev;
}
private int middleIndex() {
int size = 0;
Node cur = frontHead;
while (cur != null) {
cur = cur.next;
size++;
}
if (size % 2 == 0) {
return size / 2;
} else {
return size / 2 + 1;
}
}
}
3. 时间复杂度分析
操作 | 时间复杂度 |
---|---|
pushFront | O(1) |
pushMiddle | O(1) |
pushBack | O(1) |
popFront | O(1) |
popMiddle | O(1) |
popBack | O(1) |
4. 总结
前中后队列的实现需要对链表结构和算法策略有深入的理解。通过巧妙地利用链表,我们可以有效地维护队列的先进先出特性。链表实现的时间复杂度为 O(1),这使前中后队列成为一种高效的数据结构。
算法之旅才刚刚开始,还有更多的挑战和收获等待着我们。让我们带着对算法的热情和求知的渴望继续前进,征服算法世界!