C++ stack的使用及模拟实现

        

        stack也是STL库中非常重要的数据结构,在平常做题时使用的频率还挺高的。实际上有了前面的基础,学习STL并没有想象中那么困难,今天博主来带老铁们再来"攻坚"一个知识点。

后面会有stack的模拟实现,一定要看到最后呀,这也是了解底层很重要的知识点~

目录

stack的简单介绍

stack的使用

stack()

push()

pop()

empty()

size() 

top()

swap()

stack的模拟实现 

成员变量

成员函数

bool empty() const

size_t size() const

const T& top() const

void pop()

void push(const T& x)

注意

完整代码

stack.h

测试代码


stack的简单介绍

以前我用C实现过stack,也写过相关的博客,那就不带老铁们回顾它的结构特征了。

栈的模拟实现(顺序表来模拟)_暴走的橙子~的博客-CSDN博客

在这里我们翻译一下C++ stack文档了解一下:

 

1. stack是一种容器适配器,专门用在具有后进先出操作的上下文环境中,其删除只能从容器的一端进行元素的插入与提取操作。
2. stack是作为容器适配器被实现的,容器适配器即是对特定类封装作为其底层的容器,并提供一组特定的成员函数来访问其元素,将特定类作为其底层的,元素特定容器的尾部(即栈顶)被压入和弹出。
3. stack的底层容器可以是任何标准的容器类模板或者一些其他特定的容器类,这些容器类应该支持以下操作:
empty:判空操作
back:获取尾部元素操作
push_back:尾部插入元素操作
pop_back:尾部删除元素操作
4. 标准容器vector、deque、list均符合这些需求,默认情况下,如果没有为stack指定特定的底层容器,默认情况下使用deque。

                          

stack的使用

stack()

构造空的栈。

const container_type& ctnr = container_type():空间适配器,就是用来申请释放空间的, 这里我们不用管它,只用知道,这种申请释放空间机制效率很高就可以了。

举个栗子:

int main()
{
	stack<int> st;
	return 0;
}

我们调试一下来看:

stack<int> st:无参构造方式 ,构造时需要在stack后面加<类型>来指明stack中存储的元素类型(在这里我指明元素的类型是int)。我们发现,构造出来的对象是一个空的st。

push()

将元素val压入栈顶。 

举个栗子:

int main()
{
	stack<int> st;
	st.push(1);
	st.push(2);
	st.push(3);
	return 0;
}

我们调试一下看看情况:

我们发现三次push,依次把1 2 3进行入栈。我们来看一下入栈关系:

                              

pop()

将stack栈顶的数据出栈(删除)。 

举个栗子:

int main()
{
	stack<int> st;
	st.push(1);
	st.push(2);
	st.push(3);
	st.pop();
	st.pop();
	return 0;
}

我们调试一下来看:

 我们发现第一次pop把栈顶数据3删除了;第二次pop把栈顶数据2删除了。

empty()

判断stack里面是否为空。

如果该stack为空,就返回真(1)。如果该stack不为空,就返回假(0)。

 举个栗子:

int main()
{
	//创建一个非空栈
	stack<int> st1;
	st1.push(1);
	st1.push(2);
	st1.push(3);
	cout << st1.empty() << endl;

	//创建一个空栈
	stack<int> st2; 
	cout << st2.empty() << endl;
	return 0;
}

运行结果:

size() 

返回栈中存储的元素个数。 

举个栗子:

int main()
{
	//创建一个非空栈
	stack<int> st1;
	st1.push(1);
	st1.push(2);
	st1.push(3);
	cout << st1.size() << endl;

	//创建一个空栈
	stack<int> st2;
	cout << st2.size() << endl;
	return 0;
}

运行结果:

st1中有三个数据:1 2 3,所以st1.size()返回栈中数据的个数为3。

st2中没有数据,所以st2.size()返回的数据个数为0。 

top()

返回栈顶的数据。 

举个栗子:

int main()
{
	stack<int> st;
	st.push(1);
	st.push(2);
	st.push(3);
	while (!st.empty())
	{
		cout << st.top() << " ";
		st.pop();
	}
	cout << endl;
	return 0;
}

运行结果:

我们通过不断取出栈中数据,然后pop(),就可以发现依次拿到的就是栈顶数据。 

swap()

 交换两个栈中的数据。

举个栗子:

int main()
{
	stack<int> st1;
	st1.push(1);
	st1.push(2);
	st1.push(3);

	stack<int> st2;
	st2.push(10);
	st2.push(20);
	st2.push(30);

	st1.swap( st2);
	while (!st1.empty())
	{
		cout << st1.top() << " ";
		st1.pop();
	}
	cout << endl;

	while (!st2.empty())
	{
		cout << st2.top() << " ";
		st2.pop();
	}
	cout << endl;
	return 0;
}

运行结果:

stack的模拟实现 

       经过学习上面的stack接口。我们可以从栈的接口中看出,栈实际是一种特殊的vector,因此使用vector也完全可以模拟实现stack。(实际上底层实现是使用deque来做容器适配器,这个结构在后面我会专门写关于这个结构的博客~)

成员变量

//第二个模板参数给一个缺省值(只能从右往左给)
template<class T,class Container = deque<T>> 
private:
	Container _con;

//第二个模板参数给一个缺省值(只能从右往左给)
template<class T,class Container = deque<T>> :Container是容器适配器,在这里默认给的容器是deque<T>,这是一个双端队列,这个数据结构在后面我会写一篇博客单独介绍~

这里的Container我们可以自己指定容器,比如vector<T>。

      当然这个适配的容器必须有支持stack的函数接口,比如empty()、back()、pop_back()、push_back(x)... 因为stack内部是已经写好的,那么调用的容器就必须遵循stack里面调用接口的函数规则。

成员函数

bool empty() const

bool empty() const
{
	return _con.empty();
}

bool empty() const 
{
    return _con.empty(); //调用适配的容器的empty()的函数接口。
}

size_t size() const

size_t size() const
{
	return _con.size();
}

size_t size() const
{
    return _con.size(); //调用容器适配器的size()接口的函数。
}

const T& top() const

const T& top() const
{
	return _con.back(); //vector也支持back()接口
}

const T& top() const
{
    return _con.back(); //vector也支持back()接口

      

void pop()

void pop()
{
	_con.pop_back();
}

void pop()
{
    _con.pop_back(); //调用_con容器的pop_back()的函数接口。
}

void push(const T& x)

void push(const T& x)
{
	_con.push_back(x);
}

void push(const T& x)
{
    _con.push_back(x);//调用_con容器的push_back()的函数接口。
}

       总得来说,C++中模拟实现stack是蛮简单的,基本上就是对容器的复用,并且在C++中引入模板,体现了泛型编程的特点,stack可以存储各种类型的数据。

有兴趣的老铁们可以比较一下我用C语言模拟实现的代码差距。(链接我在上面发过来哦~)

注意

1、stack的规则是后进先出,那么stack就不支持迭代器

2、我们在使用stack时,可以这么用,stack<int,vector<int>> st,这就指明我们创建的st对象容器适配器是vector。(库里面默认的是deque)

完整代码

stack.h

#pragma once
#include"deque"
#include<iostream>
using namespace std;

namespace cyq
{
//第二个模板参数给一个缺省值(只能从右往左给)
template<class T,class Container = deque<T>> 
class stack
{
	public:
		bool empty() const
		{
			return _con.empty();
		}
		size_t size() const
		{
			return _con.size();
		}
		const T& top() const
		{
			return _con.back(); //vector也支持back()接口
		}
		void pop()
		{
			_con.pop_back();
		}
		void push(const T& x)
		{
			_con.push_back(x);
		}
	private:
		Container _con;
	};
}

测试代码

int main()
{
	cyq::stack<int> st;
	st.push(1);
	st.push(2);
	st.push(3);
	st.push(4);
	st.push(5);
	cout << st.size() << endl;
	while (!st.empty())
	{
		cout << st.top() << " ";
		st.pop();
	}
	cout << endl;

	//使用vector容器来实现
	cyq::stack<int,vector<int>> st1;
	st1.push(10);
	st1.push(20);
	st1.push(30);
	st1.push(40);
	st1.push(50);
	cout << st1.size() << endl;
	while (!st1.empty())
	{
		cout << st1.top() << " ";
		st1.pop();
	}
	cout << endl;
	return 0;
}

运行结果:

别着急,queue的使用及模拟实现马上更新~

看到这里给博主支持一下吧~

      

评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值