不知不觉,学完了栈和队列。栈和队列是两种不同的线性结构,它们可以通过两种不同的存储结构去实现。本章的难点在于,做题的时候,在读懂题目的基础上,如何从几种结构中做出最准确的选择。
在这段学习时间中,我渐渐发现,多打出来的几行代码要比课本上的概念有用得多,这句话还是挺对的。还记得老师在某一节课下课前让我们将这两种线性结构的十种情况罗列出来,我认为这别有用心。因为在对这十种结构了如指掌之后,这类型的题目也就迎刃而解了。
于是我尝试将十种情况都用代码实现出来。下面是其中一部分。如图所示。
顺序栈的实现
#include<iostream>
using namespace std;
#define Maxsize 100//栈最大空间为100struct sqstack {
int *top = NULL;//定义并且初始化栈顶指针
int *base = NULL;//定义并且初始化底指针
};void Initsqstack(sqstack &S) {//创建顺序栈函数
S.base = new int[Maxsize];//为顺序栈分配空间
S.top = S.base;//空栈状态
}bool sqstack_empty(sqstack S) {//判断空栈
if (S.top == S.base) return 1;//若空栈,则返回真
else return 0;//若非空栈,则返回假
}bool sqstack_full(sqstack S) {//判断满栈
if (S.top - S.base == Maxsize) return 1;
else return 0;
}void pushsqstack(sqstack &S, int i) {//入栈函数
if (!sqstack_full(S)) {//判断是否栈满
*S.top = i;//将值赋给顶指针所指向的空间
++S.top;//顶指针上移
}
}int popsqstack(sqstack &S) {//出栈函数
if (!sqstack_empty(S)) {//判断是否栈空
int i = 0;
--S.top;//栈顶指针下移
i = *S.top;//将栈顶指针所指空间的值取出
*S.top = 0;//栈顶指针所指空间的值取0
return i;//返回栈顶指针所指空间的值
}
}int main()
{
sqstack S;//定义并且初始化结构体
int test;
Initsqstack(S);//创建顺序栈
pushsqstack(S, 113124);//将数113124入栈
test=popsqstack(S);//栈顶所指的值出栈
cout << test;
system("pause");链栈的实现(头插法且含头结点)#include<iostream>
using namespace std;struct Linkstack{
int data;
Linkstack*next;
};void InitLinkstack(Linkstack*&S) {//创建链栈
S=new Linkstack;//为头结点分配空间
S->next=NULL;//头指针指空
}bool Linkstack_empty(Linkstack*S) {//判断空栈
if (S->next=NULL) return 1;//栈空则返回1
else return 0;
}//无需判断栈满....void pushLinkstack(Linkstack*&S,int i) {//入栈函数,无需判断栈满
Linkstack* temp;//创建新结点
temp = new Linkstack;
temp->data = i;//将值赋到数据域
temp->next = S;//新节点指向头结点
S = temp;//新节点变为头结点
}int popLinkstack(Linkstack*&S){//出栈函数
if (!Linkstack_empty(S)) {//判断空栈
int i = 0;
i = S->data;//取出头结点数据域的值
S = S->next;//首元结点变为头结点
return i;//返回取出的值
}
}
int main()
{
Linkstack *S;//创建头指针
int test = 1;
InitLinkstack(S);//初始化链栈
pushLinkstack(S, 113124);//数113124入栈
test = popLinkstack(S);//头结点数据域的值出栈
cout << test;
system("pause");
return 0;
}链队的实现(尾插法且含头结点)#include<iostream>
using namespace std;struct Linkqueue {
int data;
Linkqueue*next = NULL;
};Linkqueue* InitLinkqueue(Linkqueue*&S) {//创建链队
Linkqueue*rear = NULL;//定义尾指针
S = new Linkqueue;//创建头结点
S->next = NULL;//头结点指空
rear = S;//初始化头指针
return rear;//返回尾指针
}bool Linkqueue_empty(Linkqueue*S) {//判断队空
if (S->next == NULL) return 1;//若队空,则返回1
else return 0;//若非队空,则返回0
}void pushLinkqueue(Linkqueue*&S,Linkqueue*rear,int i) {//入队函数
Linkqueue*temp = NULL;//创建新结点
temp = new Linkqueue;//为新结点分配空间
temp->next = NULL;//新结点的指针域指空
temp->data = i;//将值赋给新结点的数据域
rear->next = temp;//将新结点连上链队
rear = temp;//尾指针后移
}int popLinkqueue(Linkqueue*&S) {//出队函数
if (!Linkqueue_empty(S)) {
int i = 0;
i = S->next->data;
S->next = S->next->next;
return i;
}
}
int main()
{
Linkqueue*S = NULL,* S_rear = NULL;
int test = 1;
S_rear=InitLinkqueue(S);
pushLinkqueue(S, S_rear, 113124);
test=popLinkqueue(S);
cout << test;
system("pause");
return 0;
}
在做PTA的时候,面对银行业务那道题的时候,我遇到了问题。这道题我的思想是,采用链队的结构,然后将这道题分成两个队列,分别是奇数队列A和偶数队列B。在输入队列的时候,从链队的尾部插入数据,然后输入的时候,从链队的头部进行输出,并且A队列每输出两次,B队列就输出一次。但是在输出的时候,我遇到的了S->next=null报错,这里卡住了半天。后来在对一条条语句进行注释的时候,发现A队列第二次输出的时候没有判断队空的情况,于是报错。最后改了之后,终于成功了。以后要注意,无论是在顺序结构中还是在链式结构中,都需要注意判断栈/队空以及栈/队满的情况。
下面分享一下本阶段学习中的一些课外资料:
1.关于头结点和尾指针的使用:
https://blog.csdn.net/imjaron/article/details/78991668
2.重复子问题:
https://blog.csdn.net/every__day/article/details/88174082
上一阶段的学习中,做到了花时间看课本,也花时间多打了代码,复习看了课本,但是最近网安事情比较多,没能花时间做到课前预习,没花时间看下C语言的书,复习的时候可能会比较吃力。
接下来的学习中,我要尽力做到课前预习,花时间看看C语言,并且把之前实践二的题做完,然后继续坚持多打代码,花时间看课本,巩固好已经掌握好的知识。
最后吐槽一下博客园,打的几百字活生生地不见了!