前言
对于这一章作业的难点,我个人觉得老师有点太为难我们了。既然这么多同学想要我出博客,那我就给大家解析一下吧。
选择题
- 第十二题如果是直接百度的话,不难得出答案 D,该题其实就是逆波兰表达式的雏形。(有一些大厂的面试题中有出现过)
但是如果有同学想要深入学习的话,可以看看我java版本的数据结构与算法,里面有详细说明
起飞
大题部分
第一与第二题
- 由于此次作业可重用部分很多,所以我把第一跟第二题放在同一段代码里面展示
- 希望大家能认真思考,我只是为了方便大家理解,毕竟能敲出来才能算学到东西
- 跟第二章一样,我们首先需要创建两个类,队列类与栈类并且给它们添加相对应的方法
- 根据第一小题的要求,我们需要创建一个环形队列,认真思考一下,不难发现队尾节点的下一个节点就是第一个节点,当队尾节点的下一个节点为自己时,证明此时队列为空
- 根据第二小题的要求,我们拿第一小题的队列,然后创建一个栈类,并且定义一个变量记录栈内有多少个元素(方便我们遍历),进行以下操作:
- 将所有元素出栈并入队;
- 依次将队列元素出队,如果是偶数结点,则再入队,如果是奇数结点,则入栈;
- 将奇数结点出栈并入队;
- 将偶数结点出队并入栈;
- 将所有元素出栈并入队;
- 将所有元素出队并入栈即为所求。
- 所以说,第二题的难点就是创建相应的类,并且进行相应的操作,如果说步骤的话,直接看main函数里面的批注就足够让同学们理解了。
- 代码如下
#include <iostream>
using namespace std;
class Node
{
public:
int data;
Node *next;
Node(int da = 0, Node *p = NULL)
{
this->data = da;
this->next = p;
}
};
class CircleQueue
{
private:
Node *node; // 工作节点,用于保存临时数据
Node *rear; // 队列尾巴
public:
CircleQueue() { node = rear = NULL; };
void Enqueue(int i);
int Dequeue();
void PrintQueque();
};
class Stack
{
private:
Node *bottom; // 表示栈底
Node *node; //临时节点,用于保存存入的数
int i; //记录该栈保存了多少个元素
public:
Stack() { bottom = new Node(0,NULL); i=0; }; //初始化
int pop(); // 出栈
void push(int num); //入栈
bool isEmpty(); //判斷栈是否为空
int getIndex();//这里是为了返回栈里面有多少个元素 ,方便我们后面创建数组 保存
};
bool Stack::isEmpty()
{
return i == 0;
}
int Stack::getIndex(){
return i;
}
void Stack::push(int num)
{
node = new Node(num); //临时节点获取到数
Node *p = bottom; //工作节点获取栈底
while (bottom)
{
if (p->next == NULL)
{
break;
}
p = p->next; //往下遍历到栈顶
}
p->next = node;
i++; //记录存入数据
cout<<num<<" 入栈"<<endl;
}
int Stack::pop()
{
if (isEmpty())
{
cout << "栈空" << endl;
return -1;
}
Node *p = bottom; //获取工作节点
while (true)
{
if (p->next->next == NULL)
{ //这一步是为了获取栈顶的下一个节点
break;
}
p = p->next;
}
int value = p->next->data;
node = p->next; //保存该节点是为了 后面垃圾回收
p->next = NULL;
i--;
cout<<value<<" 出栈"<<endl;
delete node;
return value;
}
void CircleQueue::Enqueue(int i)
{ // 传入我们要添加的值
node = new Node(i);
cout << "入列" << node->data << endl;
if (rear == NULL)
{
rear = node;
rear->next = node; //自己指向自己
}
else
{
node->next = rear->next; //当前节点的next指向尾结点的下一个节点(也就是第一个节点)
rear->next = node; //尾结点的next 指向 当前节点
rear = node; //这样使 当前节点变成尾结点
}
};
int CircleQueue::Dequeue()
{
Node *u;
int num;
if (rear == NULL) //此时队列为空
{
throw "表空";
}
else
{
node = rear->next;
u = node;
num = node->data;
if (node == rear)
{
rear = NULL;
}
else
{
rear->next = node->next;
}
cout << "出列" << num << endl;
return num;
}
}
void CircleQueue::PrintQueque()
{
if (rear == NULL)
{
cout << "该表为空"<<endl;
return;
}
while (true)
{
node = node->next;
cout << node->data << " ";
if (node == rear)
{
node=NULL;
cout << endl;
return;
}
}
}
int main()
{
CircleQueue quque;
Stack stack;
stack.push(1);
stack.push(2);
stack.push(3);
stack.push(4);
stack.push(5);
stack.push(6);
stack.push(7);
stack.push(8);
stack.push(9);
stack.push(10); // 依次入栈 初始化
int index = stack.getIndex(); //得到 栈共有几个元素
cout<<index<<endl;
for(int i=0;i<index;i++){
quque.Enqueue(stack.pop()); //遍历一次 ,入队列
}
quque.PrintQueque(); // 此时队列的数据为 10 9 8 7 6 5 4 3 2 1
int num; //定义一个遍历保存每一个数
for(int i=0;i<index;i++){
num = quque.Dequeue();//出队列,获取到一个值
if(i%2==0){ // 判断为第 偶个节点,重新入队列
quque.Enqueue(num);
}else { // 判断为 奇 个节点 入栈 最后会得到 1 3 5 7 9
stack.push(num);
}
}
quque.PrintQueque(); // 此时队列的数据为 10 8 6 4 2
for (int i=0;i<index/2;i++){
num = stack.pop();
quque.Enqueue(num);
}
quque.PrintQueque(); // 此时队列的数据为 10 8 6 4 2 1 3 5 7 9
// 将所有的偶数节点入栈
for(int i=0;i<index/2;i++){
num = quque.Dequeue(); //继续出队
stack.push(num); //入栈
}
// 所有元素出栈再入列
for(int i=0;i<index/2;i++){
num = stack.pop();
quque.Enqueue(num);
}
quque.PrintQueque(); // 1 3 5 7 9 2 4 6 8 10
// 此时 依次入栈就是答案啦
for(int i=0;i<index;i++){
num = quque.Dequeue(); //继续出队
stack.push(num); //入栈
}
quque.PrintQueque(); // 此时 队列空了
// 我们将所有元素出栈,便可看到答案
for(int i=0;i<index;i++){
num = stack.pop();
quque.Enqueue(num);
}
quque.PrintQueque(); // 10 8 6 4 2 9 7 5 3 1
cout<<"撒花!!"<<endl;
}
第四题
- 该题还算比较简单,就是做一个带头结点环形链表嘛,我们直接拿上面那题的环形队列来改改就好了
- 代码如下
#include <iostream>
using namespace std;
class Node
{
public:
int data;
Node *next;
Node(int da = 0, Node *p = NULL)
{
this->data = da;
this->next = p;
}
};
class CircleQueue
{
private:
Node *node; // 工作节点,用于保存临时数据
Node *rear; // 队列尾巴
Node *front; //头结点
int size; // 队列最大长度
int index; //记录有多少个元素了
int flag; //题目要求
public:
CircleQueue()
{
rear = front = new Node();
node = NULL;
size = 15;
flag = index = 0;
};
void Enqueue(int i);
int Dequeue();
void PrintQueque();
};
void CircleQueue::Enqueue(int i)
{ // 传入我们要添加的值
if (flag && rear == front)
{
cout << "队列满了" << endl;
return;
}
node = new Node(i);
cout << "入列" << node->data << endl;
if (front->next == NULL)
{
front->next = node;
rear = node;
rear->next = front; // 尾结点连着头结点
}
else
{
rear->next = node; // 尾结点与工作节点相连
node->next = front; // 工作节点与头结点相连
rear = node; //让工作节点变成尾结点
}
index++; // 每次插入都加一
if (index == size)
{
rear = front; //按照题意操作
flag = 1; //此时刚好满了
}
};
int CircleQueue::Dequeue()
{
Node *u;
int num;
if (rear == front && flag == 0) //此时队列为空
{
// throw "表空";
cout << "该表为空" << endl;
return -1;
}
else
{
node = front->next; //第一个元素
u = node;
num = node->data;
if (node == rear)
{
rear = front;
}
else
{
front->next = node->next;
}
cout << "出列" << num << endl;
return num;
}
index--;
if (!flag)
{
flag = 0;
}
}
void CircleQueue::PrintQueque()
{
if (rear == front && flag==0)
{
cout << "该表为空" << endl;
return;
}
node = front; // 这一步要注意,我们遍历要用工作节点,不然会丢失头结点
while (true)
{
node = node->next;
cout << node->data << " ";
if (node->next == front) //证明已经绕了一圈了,可以跑路了
{
node = NULL;
cout << endl;
return;
}
}
}
int main()
{
CircleQueue queue;
queue.Enqueue(1);
queue.Enqueue(2);
queue.Enqueue(3);
queue.Enqueue(4);
queue.Enqueue(5);
queue.Enqueue(1);
queue.Enqueue(2);
queue.Enqueue(3);
queue.Enqueue(4);
queue.Enqueue(5);
queue.Enqueue(1);
queue.Enqueue(2);
queue.Enqueue(3);
queue.Enqueue(4);
queue.Enqueue(5);
queue.Enqueue(1);
queue.Enqueue(2);
queue.Enqueue(3);
queue.Enqueue(4);
queue.Enqueue(5);
queue.Dequeue();
queue.PrintQueque();
}
后记
- 加油!!!!今晚决战到天亮 <( ̄▽ ̄)/,如果有bug跟我讲一下,我改改。
- 尽量别复制粘贴,学到东西才是自己的,我也把解题思路写得比较详细了,理解理解换个思路试试嘛