考研笔记整理~🥝🥝
之前的博文链接在此:数据结构03:栈、队列和数组_-CSDN博客~🥝🥝
本篇作为链表的代码补充,供小伙伴们参考~🥝🥝
- 第1版:王道书的课后习题~🧩🧩
编辑:梅头脑🌸
参考用书:王道考研《2025年 数据结构考研复习指导》
目录
🧵01 不牺牲存储单元的单链表
🧵02 队列元素逆置
🧵03 利用两个栈模拟队列
🧵04 链栈
🔚结语
🧵01 不牺牲存储单元的单链表
🧩题目
若希望循环队列中的元素都能得到利用,则需设置一个标志域 tag,并以 tag 的值为 0或1来区分队头指针 front 和队尾指针 rear 相同时的队列状态是“空”还是“满”试编写与此结构相应的入队和出队算法。
📇解题思路
虽然 入栈和出栈的指针判断均为 front == rear,但是考虑到仅入栈会导致栈满,出栈是导致栈空,因为,入栈与出栈的条件如下:
- tag == 1(上一次为入队操作) && front == rear 时,表示栈满;
- tag == 0(上一次为出队操作) && front == rear 时,表示栈空;
⌨️解题代码
#include <iostream>
using namespace std;const int MaxSize = 5;
typedef struct {int data[MaxSize];int front, rear;int tag;
}SeQueue;class Queue {
private:SeQueue* q;
public:Queue();~Queue();bool IsEmpty();bool IsFull();bool EnQueue(int x);bool DeQueue(int& x);
};Queue::Queue() {q = new SeQueue;q->front = q->rear = 0;q->tag = 0;
}
Queue::~Queue() {delete q;
}
bool Queue::IsEmpty() {if (q->front == q->rear && q->tag == 0) { cout << "队列为空"; return true; }else { cout << "队列不空"; return false; }
}
bool Queue::IsFull() {if (q->front == q->rear && q->tag == 1) { cout << "队列已满"; return true; }else { cout << "队列未满"; return false; }
}
bool Queue::EnQueue(int x) {if (IsFull() == true) { cout << " 入队失败" << endl; return false; }q->data[q->rear] = x;q->rear = (q->rear + 1) % MaxSize;q->tag = 1;cout << " 元素" << x << "入队成功" << endl; return true;
}
bool Queue::DeQueue(int& x) {if (IsEmpty() == true) { cout << " 出队失败" << endl; return false; }x = q->data[q->front];q->front = (q->front + 1) % MaxSize;q->tag = 0;cout << " 元素" << x << "出队成功" << endl; return true;
}int main()
{Queue q;int x;q.EnQueue(1);q.EnQueue(2);q.EnQueue(3);q.EnQueue(4);q.EnQueue(5);q.EnQueue(6); // 队列已满, 入队失败q.DeQueue(x); cout << "出队元素:" << x << endl;q.DeQueue(x); cout << "出队元素:" << x << endl;q.DeQueue(x); cout << "出队元素:" << x << endl;q.DeQueue(x); cout << "出队元素:" << x << endl;q.DeQueue(x); cout << "出队元素:" << x << endl;q.DeQueue(x); // 队列为空, 出队失败return 0;
}
🧵02 队列元素逆置
🧩题目
只是一个队列,S是一个空栈,实现将队列中的元素逆置的算法。
📇解题思路
先把队的东西导入栈,再次出栈入队时即可实现逆序存储~
⌨️解题代码
#include <iostream>
#include <queue>
#include <stack>
using namespace std;bool Reverse(queue<int>& q) {stack<int> s;// 队列q中的元素全部入栈swhile (!q.empty()) {s.push(q.front());q.pop();}// 栈s中的元素全部入队列qwhile (!s.empty()) {q.push(s.top());s.pop();}return true;
}int main() {queue<int> q;q.push(1);q.push(2);q.push(3);bool result = Reverse(q);while (!q.empty()) {cout << q.front() << " ";q.pop();}return 0;
}
🧵03 利用两个栈模拟队列
🧩题目
利用两个栈 S1 和 S2 来模拟一个队列,已知栈的4个运算定义如下:
Push(S,x); //元素x入栈 s
Pop(S,x); //s出栈并将出栈的值赋给x
StackEmpty(S); //判断栈是否为空
StackOverflow(S); //判断栈是否满
如何利用栈的运算来实现该队列的3个运算(形参由读者根据要求自己设计)?
Engueue; //将元素x入队
Dequeue; //出队,并将出队元素存储在x中
QueueEmpty; //判断队列是否为空
📇解题思路
入栈的时候直接进S1,但是出栈时就不能直接从S1出栈了:栈顶元素出栈,不满足队列要求;
然而,S1的元素导入S2就可以实现一个负负得正的效果,因此,出栈的时候,先把S1的元素搬入S2,然后直接从S2中出栈~
⌨️解题代码
#include <iostream>
#include <stack>
using namespace std;const int MaxSize = 5;class Queue {
private:stack<int> s1;stack<int> s2;int size;
public:Queue();~Queue();bool Enqueue(int x);bool Dequeue(int& x);bool QueueEmpty();
};Queue::Queue() {size = 0;
}
Queue::~Queue() {
}
bool Queue::Enqueue(int x) {if (size == MaxSize) {cout << "队列已满" << endl;return false;}s1.push(x);size++;cout << "元素" << x << "入队成功" << endl;return true;
}
bool Queue::Dequeue(int& x) {if (size == 0) {cout << "队列为空" << endl;return false;}// 如果s2为空, 则将s1中的元素全部转移到s2中;否则s2不为空, 元素直接出队if (s2.empty()) {while (!s1.empty()) {s2.push(s1.top());s1.pop();}}x = s2.top();s2.pop();size--;cout << "元素" << x << "出队成功" << endl;return true;
}
bool Queue::QueueEmpty() {if (size == 0) {cout << "队列为空" << endl;return true;}else {cout << "队列不空" << endl;return false;}
}int main() {Queue q;int x;q.Enqueue(1); // 栈S1:1,栈S2:空q.Enqueue(2); // 栈S1:1 2,栈S2:空q.Enqueue(3); // 栈S1:1 2 3,栈S2:空q.Dequeue(x); // 栈S1:空,栈S2: 3 2q.Enqueue(4); // 栈S1:4,栈S2:3 2q.Enqueue(5); // 栈S1:4 5,栈S2:3 2q.Enqueue(6); // 栈S1:4 5 6,栈S2:3 2q.Dequeue(x); // 栈S1:4 5 6,栈S2:3 q.Enqueue(7); // 栈S1:4 5 6 7,栈S2:3q.Enqueue(8); // 队列已满, 入队失败q.Dequeue(x); // 栈S1:4 5 6 7,栈S2:空q.Dequeue(x); // 栈S1:空,栈S2:7 6 5 4q.Dequeue(x); // 栈S1:空,栈S2:7 6 5q.Dequeue(x); // 栈S1:空,栈S2:7 6q.Dequeue(x); // 栈S1:空,栈S2:7q.Dequeue(x); // 队列为空, 出队失败return 0;
}
🧵04 链栈
🧩题目
【2019 统考真题】请设计一个队列,要求满足:①初始时队列为空;②入队时,允许增加队列占用空间;③出队后,出队元素所占用的空间可重复使用,即整个队列所占用的空间只增不减;④入队操作和出队操作的时间复杂度始终保持为0(1)。请回答:
1)该队列是应选择链式存储结构,还是应选择顺序存储结构?
2)画出队列的初始状态,并给出判断队空和队满的条件。
3)画出第一个元素入队后的队列状态。
4)给出入队操作和出队操作的基本过程。
📇算法思路
- 链栈可以灵活增加队列占用空间,满足题目要求;而如果使用动态循环数组,平时查询和删除的时间复杂度是O(1),但是扩容的时间复杂度是O(n),这一点就不用考虑了~
- 如果元素出队不想占用空间,那front指针直接从head后移就可以了,移动到front == rear,就是移动到末尾了~
- emm...不过以下的代码,还是实现了删除的功能(感觉一直占用空间不删除怪怪的...)
⌨️算法代码(单链表版本)
#include <iostream>
using namespace std;typedef struct LinkNode {int data;LinkNode* next;LinkNode() : data(0), next(nullptr) {}LinkNode(int x) : data(x), next(nullptr) {}
}LinkNode;class LinkQueue {
private:LinkNode* head;LinkNode* front;LinkNode* rear;
public:LinkQueue();~LinkQueue();bool IsEmpty();bool EnQueue(int x);bool DeQueue(int& x);
};LinkQueue::LinkQueue() {head = new LinkNode;front = rear = head;
}
LinkQueue::~LinkQueue() {delete head;
}
bool LinkQueue::IsEmpty() {if (front->next == nullptr) { cout << "队列为空 "; return true; }else { cout << "队列不空 "; return false; }
}
bool LinkQueue::EnQueue(int x) {LinkNode* p = new LinkNode(x);if (p == nullptr) { cout << "出队失败" << endl; return false; }rear->next = p;rear = p;cout << "元素" << x << "入队成功" << endl; return true;
}
bool LinkQueue::DeQueue(int& x) {if (IsEmpty() == true) { cout << "入队失败" << endl; return false; }LinkNode* p = front->next;x = p->data;front->next = p->next;delete p;cout << "元素" << x << "出队成功" << endl; return true;
}int main()
{LinkQueue q;int x;q.EnQueue(1); // 队q:1q.EnQueue(2); // 队q:1 2q.EnQueue(3); // 队q:1 2 3q.DeQueue(x); // 队q:2 3q.EnQueue(4); // 队q:2 3 4q.EnQueue(5); // 队q:2 3 4 5q.EnQueue(6); // 队q:2 3 4 5 6q.DeQueue(x); // 队q:3 4 5 6q.EnQueue(7); // 队q:3 4 5 6 7q.EnQueue(8); // 队q:3 4 5 6 7 8q.DeQueue(x); // 队q:4 5 6 7 8q.DeQueue(x); // 队q:5 6 7 8q.DeQueue(x); // 队q:6 7 8q.DeQueue(x); // 队q:7 8q.DeQueue(x); // 队q:8q.DeQueue(x); // 队q: 空q.DeQueue(x); // 队列为空, 出队失败return 0;
}
⌨️算法代码(循环单链表版本)
#include <iostream>
using namespace std;typedef struct LinkNode {int data;LinkNode* next;LinkNode() : data(0), next(nullptr) {}LinkNode(int x) : data(x), next(nullptr) {}
}LinkNode;class LinkQueue {
private:LinkNode* head;LinkNode* front;LinkNode* rear;
public:LinkQueue();~LinkQueue();bool IsEmpty();bool EnQueue(int x);bool DeQueue(int& x);
};LinkQueue::LinkQueue() {head = new LinkNode;front = rear = head;
}
LinkQueue::~LinkQueue() {delete head;
}
bool LinkQueue::IsEmpty() {if (head->next == head) { cout << "队列为空 "; return true; }else { cout << "队列不空 "; return false; }
}
bool LinkQueue::EnQueue(int x) {LinkNode* p = new LinkNode(x);if (p == nullptr) { cout << "入队失败" << endl; return false; } // 分配结点失败(内存已满rear->next = p;rear = p;rear->next = front;cout << "元素" << x << "入队成功" << endl; return true;
}
bool LinkQueue::DeQueue(int& x) {if (IsEmpty() == true) { cout << "出队失败" << endl; return false; }LinkNode* p = front->next;x = p->data;front->next = p->next;delete p;cout << "元素" << x << "出队成功" << endl; return true;
}int main()
{LinkQueue q;int x;q.EnQueue(1); // 队q:1q.EnQueue(2); // 队q:1 2q.EnQueue(3); // 队q:1 2 3q.DeQueue(x); // 队q:2 3q.EnQueue(4); // 队q:2 3 4q.EnQueue(5); // 队q:2 3 4 5q.EnQueue(6); // 队q:2 3 4 5 6q.DeQueue(x); // 队q:3 4 5 6q.EnQueue(7); // 队q:3 4 5 6 7q.EnQueue(8); // 队q:3 4 5 6 7 8q.DeQueue(x); // 队q:4 5 6 7 8q.DeQueue(x); // 队q:5 6 7 8q.DeQueue(x); // 队q:6 7 8q.DeQueue(x); // 队q:7 8q.DeQueue(x); // 队q:8q.DeQueue(x); // 队q: 空q.DeQueue(x); // 队列为空, 出队失败return 0;
}
🔚结语
博文到此结束,写得模糊或者有误之处,欢迎小伙伴留言讨论与批评,督促博主优化内容{例如有错误、难理解、不简洁、缺功能}等,博主会顶锅前来修改~😶🌫️
我是梅头脑,本片博文若有帮助,欢迎小伙伴动动可爱的小手默默给个赞支持一下,收到点赞的话,博主肝文的动力++~🌟🌟
同系列的博文:🌸数据结构_梅头脑_的博客-CSDN博客
同博主的博文:🌸随笔03 笔记整理-CSDN博客