数据结构之栈——概念原理及代码实现

栈的简介

今天给大家介绍另一种常用的数据结构——栈。(注意,栈从不同的角度定义有不同的定义,从内存分配的角度定义是指变量由系统分配内存,今天讲的是一种数据结构)它是一种先进后出的结构即FILO(first in last out)。如下图所示,数据的插入(压栈)删除(出栈)都从栈顶操作。
栈示意图
栈通常具有以下接口:

  1. 判断栈是否为空
  2. 移除栈顶元素
  3. 在栈顶增加元素
  4. 返回栈中元素数目
  5. 返回栈顶元素

栈的应用十分的广泛,如逆序输出、数制转换和特殊符号匹配等,函数的调用就是很好的栈的应用,下面我们进行顺序栈和链栈的代码实现。

顺序栈

在这里插入图片描述
如上图所示,顺序栈使用数组存储数据,读取写入数据时用游标操作。空表时top=-1,表满时top=MAXSIZE-1,MAXSIZE为栈容量。

顺序栈类声明

声明时采用模版,可以适应处理多种类型数据。

#define MAXSIZE 10

template<typename T>			
class stack
{
public:
	stack() :_index(-1) {};		//初始化空表
	~stack() {};

	bool empty() const;			//堆栈为空则返回真
	void pop();					//移除栈顶元素
	void push(T value);			//在栈顶增加元素
	int size() const;			//返回栈中元素数目
	T top() const;				//返回栈顶元素

private:
	int _index;					//游标
	T data[MAXSIZE];			//数组容量为MAXSIZE
};

顺序栈各接口实现

template<typename T>
inline bool stack<T>::empty() const
{
	if (_index == -1)
		return true;
	return false;
}

template<typename T>
inline void stack<T>::pop()
{
	if (_index == -1)
		return;
	_index--;
}

template<typename T>
inline void stack<T>::push(T value)
{
	if (_index == MAXSIZE - 1)
		return;
	data[++_index] = value;
}

template<typename T>
inline int stack<T>::size() const
{
	return _index + 1;
}

template<typename T>
inline T stack<T>::top() const
{
	if (_index == -1)
		return 0;
	return data[_index];
}

顺序栈的操作实现较为简单,需要注意的是,在压栈和出栈时首先要判断栈是否空或满。

测试

int main()
{
	stack<int> s;
	int num[] = { 1,2,3,4,5,6 };
	for (int i = 0; i < sizeof(num)/sizeof(int); i++)
	{
		s.push(num[i]);
	}
	cout << "栈容量:" << s.size() << endl;
	while (!s.empty())
	{
		int value = s.top();
		printf("%d ", value);
		s.pop();
	}
	getchar();
}

输出:

压栈:1 2 3 4 5 6
栈容量:6
出栈:6 5 4 3 2 1

链栈

在这里插入图片描述
如图所示,链栈采用链式结构,每个节点包括一个数据元素和一个指向下一层节点的指针,栈底节点指针指向空。链栈没有最大容量限制。

链栈类声明

仍然使用模版。

/**********节点定义*********/
template<typename T>
struct ListNode
{
	T m_nValue;
	ListNode* m_pNext;
};
/**********链栈类**********/
template<typename T>
class LStack
{
public:
	LStack();
	~LStack();
private:
	ListNode<T>* p_Top;			//指向下一层节点指针
	int _size;					//节点数量
public:
	bool empty() const;			//堆栈为空则返回真
	void pop();					//移除栈顶元素
	void push(T value);			//在栈顶增加元素
	int size() const;			//返回栈中元素数目
	T top() const;				//返回栈顶元素
};

链栈类实现

与顺序栈不同,链栈压栈时不需要判断栈是否满。

template<typename T>
LStack<T>::LStack()		//构造空栈
{
	_size = 0;
	p_Top = nullptr;
}

template<typename T>
LStack<T>::~LStack()
{
}

template<typename T>
inline bool LStack<T>::empty() const
{
	if (p_Top == nullptr)
		return true;
	return false;
}

template<typename T>
inline void LStack<T>::pop()
{
	if (p_Top == nullptr)		//判断栈是否空
		return;
	ListNode<T>* r = p_Top;
	p_Top = p_Top->m_pNext;
	delete r;
}

template<typename T>
inline void LStack<T>::push(T value)
{
	ListNode<T>* r = new ListNode<T>;
	r->m_nValue = value;
	r->m_pNext = p_Top;
	p_Top = r;
	_size++;
}

template<typename T>
inline int LStack<T>::size() const
{
	return _size;
}

template<typename T>
inline T LStack<T>::top() const
{
	if (!p_Top)
		return 0;
	return p_Top->m_nValue;
}

测试

int main()
{
	LStack<int> s;
	int num[] = { 1,2,3,4,5,6 };
	cout << "压栈:";
	for (int i = 0; i < sizeof(num)/sizeof(int); i++)
	{
		s.push(num[i]);
		cout << num[i] << " ";
	}
	cout << endl;
	cout << "栈容量:" << s.size() << endl<<"出栈:";
	while (!s.empty())
	{
		int value = s.top();
		printf("%d ", value);
		s.pop();
	}
	getchar();
}

输出:

压栈:1 2 3 4 5 6
栈容量:6
出栈:6 5 4 3 2 1

操作与效果和顺序栈一样。

总结

栈分为顺序栈和链栈,在需要逆序使用或操作数据时非常方便。但因为栈通常不处理特别大量的数据,所以栈通常是定长的即有最大容量。所以我们一般使用顺序栈。但理解链栈的实现也非常有必要。(最后声明本文所有图片皆引用网络)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值