数据结构 之 栈

编写了栈的类模板,实现了对不同类型对象基本的push、pop、清空、遍历、去长度、判断空满的功能,然后应用到了进制转换和括号匹配中去。

MyStack.h

#ifndef MYSTACK_H
#define MYSTACK_H

#include<iostream>
#include"MyStack.h"
#include<string>
//#include"Coordinate.h"//已成为通用的模板,所以不需要包含点类
using namespace std;

template<typename T>
class MyStack
{
public:
	MyStack(int size);//分配内存空间,设置栈容量,栈顶
	~MyStack();//回收栈空间
	bool stackEmpty();
	bool stackFull();
	void clearStack();
	int stackLength();
	void push(T elem);
	bool pop(T &elem);
	T pop();
	void stackTraverse(bool isFromBottom);
private:
	int m_iSize;//容量
	int m_iTop;//栈顶,栈中元素个数
	T *m_pBuffer;//栈空间指针
};



template<typename T>
MyStack<T>::MyStack(int size)//分配内存空间,设置栈容量,栈顶
{
	m_iSize = size;
	m_pBuffer = new T[m_iSize];
	m_iTop = 0;//栈顶为0
}

template<typename T>
MyStack<T>::~MyStack()//回收栈空间
{
	delete []m_pBuffer;
}

template<typename T>
bool MyStack<T>::stackEmpty()
{
	if(m_iTop == 0){
		return true;
	}
	return false;
}

template<typename T>
bool MyStack<T>::stackFull()
{
	if(m_iTop == m_iSize){
		return true;
	}
	return false;
}

template<typename T>
void MyStack<T>::clearStack()
{
	m_iTop = 0;//意味着栈内放的值都是无效的
}

template<typename T>
int MyStack<T>::stackLength()
{
	return m_iTop;
}

template<typename T>
void MyStack<T>::push(T elem)
{
	if(stackFull()){
		throw string("已满!");//异常的两种处理,一种是try catch throw,一种是如pop那种返回bool值的方法
		//cout << "已满!" << endl;
	}else{//注意这里elem赋值是浅拷贝,调用到的是默认拷贝构造函数,是直接赋值,如果Coordinate类成员有指针类型的成员,那就需要自己定义一个拷贝函数并且用深拷贝
		*(m_pBuffer+m_iTop) = elem;//m_pBuffer[m_iTop]=elem也可以
		m_iTop ++;
	}
}

template<typename T>
T MyStack<T>::pop()
{
	if(stackEmpty()){
		throw string("已空!");
	}else{
		m_iTop --;
		return *(m_pBuffer+m_iTop);
	}

}

template<typename T>
bool MyStack<T>::pop(T &elem)
{
	if(stackEmpty()){
		cout << "已空!" << endl;
		return false;
	}else{
		m_iTop --;
		elem = *(m_pBuffer+m_iTop);
		return true;
	}
}

template<typename T>
void MyStack<T>::stackTraverse(bool isFromBottom)
{
	if(!isFromBottom){
		for(int i = m_iTop-1;i >= 0;i--){
			cout << m_pBuffer[i];//所以要求T类型对象都要重载运算符<<
			//m_pBuffer[i].printCoordinate();
		}
		cout << endl;
	}else{
		for(int i = 0;i < m_iTop;i++){
			cout << m_pBuffer[i];
			//m_pBuffer[i].printCoordinate();
		}
		cout << endl;
	}
}







#endif

没有MyStack.cpp,因为vs编译器不支持类模板声明和定义的分开,所以全都放在MyStack.h里


Coordinate.h

#ifndef COORDINATE_H
#define COORDINATE_H
#include<ostream>//因为用到了ostream类型
using namespace std;

class Coordinate
{
	friend ostream& operator << (ostream &out,Coordinate &elem);//都用引用,节省空间
public:
	Coordinate(int x = 0,int y = 0);
	void printCoordinate();
private:
	int m_iX;
	int m_iY;


};//分号别忘











#endif


Coordinate.cpp


#include"Coordinate.h"
#include<iostream>
using namespace std;

Coordinate::Coordinate(int x,int y)
{
	m_iX = x;
	m_iY = y;
}
void Coordinate::printCoordinate()
{
	cout << "(" << m_iX << "," << m_iY << ")" << endl;
}

demo.cpp

#include<iostream>
#include<stdlib.h>
#include<string>
#include"MyStack.h"
#include"Coordinate.h"
using namespace std;
/*
栈 类模板
可以让栈放任何数据类型的数据



*/
#define BINARY 2
#define OCTONARY 8
#define HEXADECIMAL 16

ostream& operator << (ostream &out,Coordinate &elem);//不再需要friend标识符

int main()
{
//栈模板验证
	//MyStack<Coordinate> *pStack = new MyStack<Coordinate>(5);//选择不一样的类型的栈
	//MyStack<char> *pStack1 = new MyStack<char>(2);
	//try{
	//	pStack->push(Coordinate(1,2));//底
	//	pStack->push(Coordinate(2,2));
	//	pStack->push(Coordinate(3,2));
	//	pStack->push(Coordinate(4,2));
	//	pStack->push(Coordinate(5,2));//顶
	//	pStack->stackTraverse(0);
	//	Coordinate elem = pStack->pop();
	//	//cout << elem << endl;
	//	elem.printCoordinate();
	//	pStack->stackTraverse(0);
	//	pStack->push(Coordinate(6,2));
	//	cout << pStack->stackLength() << endl;
	//	pStack->clearStack();
	//	pStack->pop(elem);
	//	if(pStack->stackEmpty()){
	//		cout << "空!" << endl;
	//	}
	//	if(pStack->stackFull()){
	//		cout << "满!" << endl;
	//	}

	//	pStack1->push('d');
	//	pStack1->push('s');
	//	pStack1->stackTraverse(0);
	//}
	//catch(string &str){
	//	cout << str << endl;
	//}
	//cout << "test" << endl;//catch执行完后也会继续执行
	//delete pStack;
	//pStack = NULL;


//应用:实现十进制到任意进制转换
	//MyStack<int> *pStack = new MyStack<int>(30);
	//char num[] = "0123456789abcdef";//考虑到16进制打印显示abcdef的问题

	//int N = 1354;
	//int M = 0;
	//int d = HEXADECIMAL;
	//while(N != 0){
	//	M = N%d;
	//	pStack->push(M);
	//	N = N / d;
	//}
	////pStack->stackTraverse(0);
	////int length = pStack->stackLength();
	////for(int i = 0;i != length;i++){
	////	cout << num[pStack->pop()];//pop之后,栈的长度会改变

	////}
	////cout << endl;
	//while(!(pStack->stackEmpty())){
	//	cout << num[pStack->pop()];
	//}
	//cout << endl;
	//delete pStack;


//应用:括号匹配
	MyStack<char> *pStack = new MyStack<char>(30);//纪录扫描到的字符
	MyStack<char> *pNeedStack = new MyStack<char>(30);//记录栈顶急需的字符

	char str[] = "[]]";
	char currentNeed = 0;//表示当前所需要的字符,赋一个不可见的字符初值
	for(int i = 0;i < strlen(str);i ++){
		if(str[i] != currentNeed){
			pStack->push(str[i]);
			//pNeedStack->push(currentNeed);
			//if(str[i] == '['){
			//	currentNeed = ']';
			//}else if(str[i] == '{'){
			//	currentNeed = '}';
			//}else if(str[i] == '('){
			//	currentNeed = ')';
			//}else{
			//	break;
			//}
			//用switch比较好
			switch(str[i]){
			case '[':
				if(currentNeed != 0){//之所以写到这里而不写在switch外面是为了以后扩展方便,因为不是每种情况都要进行这个判断
					pNeedStack->push(currentNeed);
				}
				currentNeed = ']';
				break;
			case '{':
				if(currentNeed != 0){
					pNeedStack->push(currentNeed);
				}
				currentNeed = '}';
				break;
			case '(':
				if(currentNeed != 0){
					pNeedStack->push(currentNeed);
				}
				currentNeed = ')';
				break;
			default:
				cout << "不匹配" << endl;
				delete pStack;
				delete pNeedStack;
				system("pause");

				return 0;
			}
		}else{
			if(!pNeedStack->pop(currentNeed)){
				currentNeed = 0;
			}
			pStack->pop();
		}
	}
	if(pStack->stackEmpty()){
		cout << "全部匹配" << endl;
	}else{
		cout << "不匹配" << endl;
	}
	delete pStack;
	delete pNeedStack;
	system("pause");
	return 0;
}

ostream& operator << (ostream &out,Coordinate &elem)
{
	out << "(" << elem.m_iX << "," << elem.m_iY << ")" << endl;
	return out;
}



猜你喜欢

转载自blog.csdn.net/zealice/article/details/78188645