贵阳网站建设多少钱?,开发网站用什么语言最好吗,wordpress停止循环,网站icp备案地C嘎嘎探索篇#xff1a;栈与队列的交响#xff1a;C中的结构艺术
前言#xff1a;
小编在之前刚完成了C中栈和队列#xff08;stack和queue#xff09;的讲解#xff0c;忘记的小伙伴可以去我上一篇文章看一眼的#xff0c;今天小编将会带领大家吹奏栈和队列的交响栈与队列的交响C中的结构艺术
前言
小编在之前刚完成了C中栈和队列stack和queue的讲解忘记的小伙伴可以去我上一篇文章看一眼的今天小编将会带领大家吹奏栈和队列的交响完成对于他们的模拟实现使各位更容器去了解它们为什么被叫做容器适配器。 文章目录 C嘎嘎探索篇栈与队列的交响C中的结构艺术1.stack的模拟实现1.1.stack类初步书写1.2.入栈函数push()的实现1.3.出栈函数pop()的模拟实现1.4.判空函数empty()的模拟实现1.5.个数函数size()的模拟实现1.6.栈顶函数top()的模拟实现 2.小警示3.queue的模拟实现3.1.queue类的初步实现3.2.入队列函数push()的模拟实现3.3.出队列函数pop()的模拟实现3.4.取队头函数front()的模拟实现3.5.取队尾函数back()的模拟实现3.6.判空函数empty()的模拟实现3.7.个数函数size()的模拟实现 4.代码展示4.1.stack4.2.queue 5.总结 正文 1.stack的模拟实现 首先我们就要先实现stack的模拟实现栈我们以前在数据结构阶段是用顺序表进行实现的小编此时也是要用一个容器来对其进行实现的我们在它的众多接口中不难发现stack是和vector是很像的所以我们想要实现出stack就是要给予vector容器进行模拟实现的当然通过上图我们知道系统是用双端队列deque进行实现的但是比其它我还是更喜欢使用vector进行模拟实现小编建议读者朋友在看我模拟实现之前倘若不了解vector是如何进行使用的可以先看我之前写过的文章来回顾一下我先不放上链接了因为在我写本文之前我还没有发布那篇文章因为等会我会使用vector的一些接口来帮助我实现出stack下面开始进入stack类的模拟实现。
1.1.stack类初步书写
我们首先需要先把我们自己写的stack定义在一个命名空间里面避免和std命名空间里面的stack起冲突因为stack是一个模版类所以我们应该用模版类的方式来书写这个类里面的参数我们对照着标准库书写即可在我们写完外层以后就是要书写内层了此时我们先定一个成员变量它的类型自然就是Container类型这个类型可以是vector可以是list甚至是string这个成员变量是为了后续数据的增删而写下面小编给出这部分代码的书写
namespace wang //保存在命名空间里面避免出现名字冲突防患于未然
{templateclass T,class Container std :: vectorT //默认使用的容器是vector也可以是list毕竟也有链式栈的存在class stack{private:Container s1; //s1是为了保存数据的增删还是需要靠它。};
}1.2.入栈函数push()的实现 可能到这里可能很多读者朋友会疑惑我为什么没有书写stack的构造函数对于对此有疑惑的读者朋友请好好的去复习一下类和对象的知识还记着类和对象知识的读者朋友都知道对于自定义类型的成员变量编译器是会自己去调用它的构造函数的如果成员变量没有构造函数的那么编译器会直接报错自定义类型需要自己写当然不写的话系统会调用默认构造函数默认构造函数有三种这只是特殊情况之一所以各位记住这一点此时s1是vector类型的它是会自己去调用自己的构造函数的我们不用瞎操心下面我们正式堆push()的实现进行讲述。
其实push()函数的实现我们仅需去复用s1中的接口即可看看上图stack的构造我们不难发现此时我们仅需在一个vector类型的尾部插入数据即可此时我们就可以去调用vector当中的尾插函数即可根本不用我们自己思考了所以这就是我前面说stack很好实现的原因我们仅需套用成员变量的接口即可这也是我让各位复习一下vector的原因下面给出代码
void push(T x) //此时我们不晓得插入啥类型的元素这就看我们显示实例化我们想要显示的了
{s1.push_back(x);
}1.3.出栈函数pop()的模拟实现
和小编上面实现入栈函数一样对于出栈函数我们也是仅需套用一下s1的接口即可通过上图我们可以知道此时的出栈操作对应着的就是把vector对象的尾部删除所以我们调用尾删函数即可下面给出代码
void pop()
{s1.pop_back();
}1.4.判空函数empty()的模拟实现
对于判空函数的模拟实现也和上面的接口类似了解vector的朋友都知道vector里面也是有一个叫做empty()的接口的我们仅需套用这个接口就好了下面小编给出代码
bool empty()
{return s1.empty();
}1.5.个数函数size()的模拟实现
对于它的模拟实现我们同样也可以套用vector的相关接口就可以实现这个个数函数由于难度不大不再多说给出代码
int size()
{return s1.size();
}1.6.栈顶函数top()的模拟实现
对于栈顶函数的模拟实现我们需要先知道栈顶是vector哪个位置的元素通过上图便可以轻松的看出来栈顶就是vector对象最后一个位置的元素此时我们仅需返回尾部元素即可此时我们可以套用vector中的back接口这个接口我虽然没讲它的功能就是返回vector最后一个位置的元素名字其实就可以知晓了。下面小编给出代码写法
T top()
{return s1.back();
}以上便就是对于stack的模拟实现是不是灰常的简单小编当时在经历完某几个容器的模拟实现之后这一模拟实现stack就感到了一阵舒爽我们仅需疯狂的套用接口就好了剩下的全靠编译器的调用了等会queue的讲解也会非常的舒服不过在讲述queue之前小编先给各位说一个小的知识点避免读者朋友踩坑。
2.小警示
对于接下来无论是容器还是适配器的模拟实现各位读者朋友千万不要让模版的声明和定义分离我忘记我模版说没说过了对于模板类型的类和函数它们的声明和定义是不可以去分离的这涉及到了分离编译的知识这部分的知识点小编通过一个图带各位简单的了解下更为详细的知识我会在模版进阶文章进行讲述其中的过程通过下图便可以知晓为什么模版的声明和定义是无法分离的。 所以我们在进行模拟实现的时候直接把声明和定义放在一个头文件即可这个知识点要牢记防止一些读者朋友犯迷糊。
3.queue的模拟实现 在讲述这个小警示以后紧接着我们就要开始进入queue的模拟实现了相信看完前文的stack的模拟实现后各位应该对于queue的模拟实现也会信心满满因为queue的接口中设计了一端进一端出因此此时我们用vector封装的话效率会变的很低根据以前我们数据机构队列的实现的检验来看用双链表是一个不错的选择而恰好我们之前list就是一个典型的双链表结构所以此时我们就是用list来帮助我们实现queue的模拟实现下面我们就进入queue的模拟实现。
3.1.queue类的初步实现
首先我们需要先完成queue的外部的书写此时和stack一样为了防止命名冲突我们需要把它放置在我们自己的命名空间内然后完成一个模板类的书写之后我们再和标准库的queue一样书写模版参量之后我们在写一个Container类型的对象就好了把它作为我们的成员变量通过它实现出队列的增删等操作下面给出这层外套
namespace wang
{templateclass T,class Container listTclass queue{private:Container s1;};
}3.2.入队列函数push()的模拟实现 对于入队列函数此时我们需要按照队列的结构来对于list对象接口进行合理使用此时我们知道入队列是从队尾入所以此时我们需要用到list里面的尾插接口来帮助我们实现这个功能下面小编给出这个代码的书写
void push(T x)
{s1.push_back(x);
}3.3.出队列函数pop()的模拟实现
对于出队列函数我们依照队列的结构发现它是从队头进行出队列操作所以此时我们就要借助list对象的头删函数来帮助我们完成出队列操作下面小编给出这个代码的书写
void pop()
{s1.poo_front();
}3.4.取队头函数front()的模拟实现
这个函数的功能名字就可以体现出来此时我们如果想要取出队头就需要知道是s1的一个我也没讲过的接口front()接口它的功能就是取出双链表第一个有效结点的元素所以它正好就可以取出队头元素下面给出代码书写
T front()
{return s1.front();
}3.5.取队尾函数back()的模拟实现
这个函数的功能同样通过名字就可以体现出来此时我们想要取出队尾就需要知道s1的back()接口他和vector一样都是取出最后一个位置的元素用它便可以取出队尾的元素下面给出代码
T back()
{return s1.back();
}3.6.判空函数empty()的模拟实现
对于判空函数无非就是判断队列里面是否为空无非就是检查成员变量是否为空此时我们仅需调用list对象的判空函数即可下面小编给出代码
bool empty()
{return s1.empty();
}3.7.个数函数size()的模拟实现
我们如果想要知道队列里面有几个有效元素直到成员对象里面有几个有效元素即可此时我们仅需套用它的size()函数即可下面给出代码
int size()
{return s1.size();
}以上便就是小编对于queue的模拟实现此时此刻的你是不是感受到了“套娃”的魅力对于适配器的模拟实现我们仅需知道合适的容器就好了剩下的就是无限的套用只能说用起来十分的舒适容器的模拟实现我认为是很复杂的这就是我到现在都没有书写容器的模拟实现的原因咳咳其实也是懒的写下面我把这些代码整合起来来帮助各位知晓一个完整的模拟实现。
4.代码展示
4.1.stack
namespace wang
{templateclass T,class Container std :: vectorTclass stack{public:void push(T x){s1.push_back(x);}void pop(){s1.pop_back();}bool empty(){return s1.empty();}int size(){return s1.size();}T top(){return s1.back();}private:Container s1;};
}
4.2.queue
namespace wang
{templateclass T,class Comtainer std :: listT class queue{public:void push(T x){s1.push_back(x);}void pop(){s1.pop_front();}int size(){return s1.size();}T front(){return s1.front();}T back(){return s1.back();}bool empty(){return s1.empty();}private:Comtainer s1;};
} 5.总结
此时此刻小编就完成了栈和队列的模拟实现是不是很轻松这直接套用别的容器接口的感觉就是舒服如果容器的模拟实现也是这样该多好当然不可能希望后来的我可以完成各种容器的模拟实现文章的书写感觉写一篇相关类型的文章可以帮助我更好的成长如果文章有错误可以在评论区点出我会定期的回复读者朋友那么各位大佬们我们下一篇文章见啦