数据结构(1)——顺序栈的实现,以及括号匹配的应用

为什么从堆栈开始?因为我觉得线性部分比较简单的是堆栈和队列,用得也比较多,有不少人觉得链表才简单啊,其实链表简单吗?链表可以派生的东西反而很多,不是一时半会可以理解的,还记得在一篇微软的招聘心得回顾文上看到,微软的面试官就问他怎样用两个链表实现一个栈。当然,现在打乱顺序是因为早在大一就学过数据结构,现在只是更深入更多样的讨论,所以就不再在意一开始教学所用的结构,这不是新手教程。

废话不多说,开始堆栈的学习。

首先,堆栈是线性表的拓展——只能在一头进行修改,所以如果是用高级语言实现的话,可以直接继承LinearList然后进行派生,但是这种方法会产生效率问题,具体看到代码以及注释。

所以我们还是选择直接实现,即自定义一个Stack基类。

/*template
class Stack::private LinearList{
	//LIFO对象
	//没有为Stack类定义析构函数,因此当Stack类型的对象被删除时,自动调用LinearList的析构函数
public:
	Stack(int MaxStackSize = 10) :LinearList(MaxStackSize) {}
	bool IsEmpty() const{
		return LinearList::IsEmpty();
	}
	bool IsFull() const{
		return (Length() == GetMaxSize());//可以在LinearList增加一个保护成员GetMaxSize(),
	}
	T Top() const{
		if (IsEmpty()) throw OutOfBounds();
		T x;
		Find(Length(), x);
		return x;
	}
	Stack& Add(const T& x){
		Insert(Length(), x);
		return *this;
	}
	Stack& Delete(T& x){
		LinearList::Delete(Length(), x);
		return *this;
	}
};
不幸的是,这类操作会但是一个效率问题。例如:
为了向堆栈中添加一个元素,首先要确定堆栈的长度length(),然后调用函数Insert()。而Insert函数首先必须判断插入操作是否会越界,然后需要付出一个for循环的开销来执行0个元素的移动
而操作符也必须要重载
所以可以把Stack定义成一个基类,而不是派生类
*/

template
class Stack{
	//LIFO对象
public:
	Stack(int MaxStackSize = 10);
	~Stack(){ delete[] stack; }
	bool IsEmpty() const { return top == -1; }
	bool IsFull() const { return top == MaxTop; }
	T Top() const;
	Stack& Add(const T& x);
	Stack& Delete(T& x);
private:
	int top;//栈顶
	int MaxTop;//最大的栈顶值
	T *stack;//堆栈元素数组
};

template
Stack::Stack(int MaxStackSize){
//Stack类构造函数
	MaxTop = MaxStackSize - 1;
	stack = new T[MaxStackSize];
	top = -1;
}

template
T Stack::Top() const{
//返回栈顶元素
	if (IsEmpty()) throw OutOfBounds();
	else return stack[top];
}

template
Stack& Stack::Add(const T& x){
	//添加元素x
	if (IsFull()) throw NoMem();
	stack[++top] = x;
	return *this;
}

template
Stack& Stack::Delete(T& x){
	//删除元素x
	if (IsEmpty()) throw OutOfBounds();
	x = stack[top--];
	return *this;
}

class OutOfBounds{
public:
	OutOfBounds() {}
};

class NoMem{
public:
	NoMem(){}
};
//使new引发NoMem异常而不是xalloc异常
void my_new_handler(){
	throw NoMem();
}
std::new_handler Old_Handler_=std::set_new_handler(my_new_handler);
程序使用模板函数来定义,和以往的方法不同。说过了这是一次回顾、总结、拓展以及深入,所以和之前的定义不同是难免的。后面的章节还会有不同方法、不同定义的实现,卖关子在这里先。

接着就来实现括号匹配。括号匹配方法也很多,仅供参考。

#include
#include
#include
#include"stack.h"
using std::cout;
using std::cin;
using std::endl;
const int MaxLength=100;//最大的字符串长度
void PrintMatchedPairs(char *expr){
//括号匹配
	Stack s(MaxLength);
	int j,length=strlen(expr);
	//从表达式中搜索(和)
	for(int i=1;i<=length;i++){
		if(expr[i-1]=='(') s.Add(i);
		else if(expr[i-1]==')'){
			try{s.Delete(j);
		cout<

因为这个程序不是太复杂,实现的图片就不放上来了(ps:CSDN的传图片功能让人捉急)。

你可能感兴趣的:(Data,structure,and,Algorithm)