重学数据结构之栈

栈是限定仅在表尾进行插入和删除操作的线性表,允许插入和删除的一端称为栈顶,另一端则为栈底。仅能对栈顶元素直接进行操作。

如图所示,初始状态下栈里有三个元素。这三个元素进入栈的顺序必然是x,y,z,出栈顺序必然是z,y,x(这里我们不考虑其他元素)。可见,先进入的元素x由于最先进入栈内,被其他进入的元素压在栈底,而最后出来,所以我们说栈具有先进后出的特性。

关于栈的使用,最常见的是括号匹配,若是左括号则入栈,遇到右括号则和栈顶元素匹配,若不对应,则匹配错误。

对于栈的操作,我们可以简单谈谈。

入栈——将元素放到栈顶;出栈——栈顶元素弹出,将栈顶的下一层元素设置为栈顶。关于这两个操作,都涉及到了栈顶位置的移动,我们在实现的时候采用指针来控制。

关于顺序栈的实现如下:

#include <iostream>
using namespace std;
const int StackSize = 1000;
template <class T>
class SeqStack
{
	public:
		SeqStack();	// 构造 
		~SeqStack(){	}	// 析构 
		void push(T x);	// 入栈 
		T pop();	// 出栈并获取栈顶元素 
		T getTop();	// 获取栈顶元素 
		int empty();// 判断栈是否为空 
	private:
		T data[StackSize];
		int top;	// 栈顶指针,为元素下标 
}; 
template <class T>
SeqStack<T>::SeqStack()
{
	top = -1;	// -1下标并不存在,表示空栈 
}

template <class T>
void SeqStack<T>::push(T x)
{
	// 顺序栈事先分配了最大空间
	// 上溢条件易被忽略 
	if(top == StackSize - 1) throw"上溢"; 
	// 入栈下标+1
	data[++top] = x;
	 
}

template <class T>
T SeqStack<T>::pop()
{
	// 出栈前需要判断栈是否为空
	// 空栈无栈顶元素可出栈
	if(top == -1)  throw"下溢";
	return data[top--]; //先弹出栈顶元素,再移动栈顶指针 
}

template <class T>
T SeqStack<T>::getTop()
{
	if(top == -1) throw"下溢";
	return data[top];
 } 
 
 template <class T>
 int SeqStack<T>::empty()
 {
 	if (top == -1 ) return 1;
 	else return 0;
 }
 
 int main()
 {
 	SeqStack<int> ss;
 	
 	ss.push(5); ss.push(8); ss.push(9); ss.push(10);
 	int m = ss.pop();
 	cout << "栈顶元素为: " << m ; 
 	m = ss.pop();
 	cout << " " << m ; 
 	m = ss.pop();
 	cout << " " << m ; 
 	m = ss.pop();
 	cout << " " << m ; 
 	return 0;
  } 

------------------------19.6.1 待续----------------------------

链栈的构造方式和单链表相似,却简单得多,唯一复杂的则是析构函数。

#include <iostream>
using namespace std;

template <class T>
struct Node
{
	T data;
	Node<T> *next;
};

template <class T>
class LinkStack
{
	public:
		LinkStack();
		~LinkStack();
		void Push(T x);	// 入栈 
		T Pop();	// 获取栈顶元素并将其出栈 
		T GetTop();	// 获取栈顶元素 
		bool Empty();	//判断是否为空栈 
	private:
		Node<T> *head;	// 栈顶指针 
};

template <class T>
LinkStack<T>::LinkStack()
{
	head = NULL;
} 
 
template <class T>
LinkStack<T>::~LinkStack()
{
	// 删除所有结点 
	while (head)
	{
		Node<T> *p = head -> next;
		delete head;
		head = p; 
	}
}

template <class T>
void LinkStack<T>::Push(T x)
{
	// 入栈操作
	// 更新当前栈顶指针 
	// 原先的栈顶指针为当前栈顶指针的下一个结点 
	Node<T> *p = new Node<T>;
	p -> data = x;
	p -> next = head;
	head = p;
}

template <class T>
T LinkStack<T>::Pop()
{
	if(head == NULL) throw "空栈"; 
	T x = head -> data;
	// 这里必须借助p指针释放旧的栈顶指针内存空间
	// 否则head为NULL 
	Node<T> *p = head;
	head = head -> next;
	delete p;
	return x; 
}

template <class T>
T LinkStack<T>::GetTop()
{
	if(head == NULL) throw"空栈";
	return head -> data;
}

template <class T>
bool LinkStack<T>::Empty()
{
	if(head == NULL) return 1;
	else return 0;
 } 
int main()
{
	LinkStack<int> ls;
	ls.Push(1); ls.Push(2); ls.Push(3);
	
	int x = ls.Pop();
	cout << "栈顶元素为" << x << endl;
	
	x = ls.GetTop(); 
	cout << "栈顶元素为" << x << endl;
	
	string str = ((ls.Empty()==1)? "空" : "非空");
	cout << "栈空否? " << str << endl;
	
	ls.Pop();
	ls.Pop(); 
	str = ((ls.Empty()==1)? "空" : "非空");
	cout << "栈空否? " << str << endl;
	
	return 0;
 } 

------------------------19.6.2 待续----------------------------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值