DS006-栈的原理-操作受限的线性表-C++ STL 栈模板stack

本篇先介绍顺序栈、链栈的原理,然后介绍C++ STL栈模板的简单用法。

一、为什么引入栈这个名词

有些应用,处理的数据具有下面的特点:

1、具有线性结构,用线性表存储

2、然而,却只需要简单的操作:仅在线性表的一端进行插入和删除。

你当然可以使用前面实现过的顺序表和链表,只不过只用到其中的部分操作而已。

有好事的前辈,偏偏为它取个名字,叫“栈”,又多一个名词,多一个负担。

线性表有两种实现方式,顺序表和链表

对应的栈也有两种。

二、顺序栈

这就要分析了,用顺序表做为栈,在哪一头进行插入删除呢?

显然在下标大的那一头插入和删除都不需要移动其他数据,效率高

因此,顺序栈的插入操作(入栈)就是在表尾插入,栈的删除操作(出栈)就是在表尾删除。



#include "stdafx.h"

#include<iostream> 
using namespace std;
//模板类,T是泛化类型
template<typename T>class stack
{//顺序栈
	T *base;//连续空间的首地址,栈底
	int listsize;//连续空间的大小
	int length;//实际元素的个数
	T *top;//栈顶
public:
	stack()
	{//构造函数
		init();
	}
	void init()
	{//对栈进行初始化
		base = new T[16];//初始时,占用16个空间,这个可以自己设置,一般是2的n次方
		listsize = 16;
		length = 0;
		top = base;
	}
	int enlarge()
	{//当L的空间不足时,本函数功能:将L的空间翻倍
	 //如果成功返回1,失败返回0

		T *newbase = new T[listsize * 2];//开辟新空间
		if (0 == newbase)
			return 0;
		for (int i = 0; i<length; i++)//把老空间已有数据拷贝到新空间
			newbase[i] = base[i];
		delete[]base;//释放掉老空间,还给操作系统
		base = newbase;//elem指向新空间首地址
		listsize = listsize * 2;//空间大小翻倍
		top = base + length;
		return 1;

	}
	void push(T x)
	{//入栈,即在顺序表尾部插入数据
		if (length == listsize)
		{//空间不足 
			enlarge();
		}

		*top = x;
		top++;
		length++;
	}

	void pop()
	{//出栈,删除顺序表表尾元素
		top--;
		length--;

	}
	int size()
	{//得到栈中元素个数
		return length;
	}
	int isEmpty()
	{//如果栈为空返回1,否则返回0
		return length == 0;
	}

	T getTop()
	{//得到栈顶元素
		return *(top - 1);

	}
	void print()
	{//测试用
		T *p = base;
		while (p < top)
		{
			cout << *p << "  ";
			p++;
		}
		cout << endl;

	}
	
	~stack()
	{
		delete[]base;
	}
};

int main()
{
	stack<int> s;

	s.push(1);
	s.push(3);
	s.push(5);
	s.print();

	int x;
	x = s.getTop();
	cout << "the top of stack is:" << x << endl;

	s.pop();
	s.print();
	s.pop();
	s.print();


	return 0;
}


三、链栈

用链表作为栈,在哪一头进行插入删除呢?

1、用单链表时,在头部插入和删除都方便。

2、用单向循环链表时,在头部插入和删除都方便;

3、用双向循环链表时,都比较方便。

因此,从复杂程度来看,用单链表实现栈,简单些。



#include "stdafx.h"

#include<iostream> 
using namespace std;
//模板类,T是泛化类型
template<typename T>class stack
{//基于单链表的栈
	struct node
	{
		T data;
		node *next;
	};
	node *head;//头结点指针	
	int length;//实际元素的个数
	
public:
	stack()
	{//构造函数
		init();
	}
	void init()
	{//对栈进行初始化
		head = new node;
		head->next = 0;
		length = 0;
	}
	
	void push(T x)
	{//入栈,即在单链表头部插入数据
		node *t;
		t = new node;
		t->data = x;
		t->next = head->next;
		head->next = t;
		
		length++;
	}

	void pop()
	{//出栈,删除单链表表头元素
		node *t;
		t = head->next;
		head->next = t->next;
		delete t;
		length--;

	}
	int size()
	{//得到栈中元素个数
		return length;
	}
	int isEmpty()
	{//如果栈为空返回1,否则返回0
		return length == 0;
	}

	T getTop()
	{//得到栈顶元素
		node *t = head->next;
		return t->data;

	}
	void print()
	{//测试用
		node *p = head->next;
		while (p)
		{
			cout << p->data << "  ";
			p=p->next;
		}
		cout << endl;

	}
	
	~stack()
	{
		delete[]head;
	}
};

int main()
{
	stack<int> s;

	s.push(1);
	s.push(3);
	s.push(5);
	s.print();

	int x;
	x = s.getTop();
	cout << "the top of stack is:" << x << endl;

	s.pop();
	s.print();
	s.pop();
	s.print();


	return 0;
}


四、C++ STL的stack

在C++ STL中已经定义好了stack模板类。

以后我们直接用即可。



#include "stdafx.h"

#include<stack>//C++ STL 栈模板头文件
#include<iostream> 
using namespace std;

template<typename T>

int main()
{
	stack<int> s;//定义一个整数栈
	int x;
	
	s.push(1);//入栈
	x = s.top();//得到栈顶元素
	cout << "the top of stack is:" << x << endl;

	s.push(3);
	x = s.top();
	cout << "the top of stack is:" << x << endl;

	s.push(5);
	x = s.top();
	cout << "the top of stack is:" << x << endl;
	
	

	s.pop();//出栈
	x = s.top();
	cout << "the top of stack is:" << x << endl;
	s.pop();
	x = s.top();
	cout << "the top of stack is:" << x << endl;


	return 0;
}


还有:s.size()得到栈中元素个数;

s.empty()判断栈是否为空;

由于其没有提供下标操作,因此想查看其中的所有元素,即遍历,就很复杂。

可以这样,把元素从栈中取出打印,存到另一个栈中,最后再恢复过去。

template<typename T>
void print(stack<T> &s)
{
	stack<T> s2;
	T x;
	while (s.empty() == false)
	{
		x = s.top();
		cout << x << " ";
		s2.push(x);
		s.pop();
	}
	cout << endl;

	while (s2.empty() == false)
	{
		x = s2.top();
		s2.pop();
		s.push(x);
	}

}

猜你喜欢

转载自blog.csdn.net/weixin_43917370/article/details/108571420