栈结构:先进后出,后进先出,像叠盘子一样,先叠的后用。
代码github地址 https://github.com/hitskyer/course/tree/master/dataAlgorithm/chenmingming/stack
1.顺序栈(数组存储,需给定数组大小,到达容量需要copy转移数据)
1.1 头文件 arrStack.h
//
// Created by mingm on 2019/3/27.
//
#ifndef STACK_ARRSTACK_H
#define STACK_ARRSTACK_H
typedef unsigned int UINT;
template <class T>
class arrStack
{
public:
arrStack(int capacity); // 初始化栈
~arrStack(void); // 析构栈
bool Empty() const; // 判断是否为空
bool IsFull() const; //判断栈是否满了
void Clear(); // 则清空栈
T& GetTop() const; // 得到栈顶元素
UINT GetLength() const; // 返回栈的长度
void Push(T &data); //往栈中压入数据
void Expand(); //栈扩容
void Pop(); //将栈顶数据弹出
void print(); //自己加的接口,打印输出stack内容
private:
int m_pTop; // 栈顶指针
UINT m_nStackLen; // 栈容量
T* arr; //数组arr
};
#endif //STACK_ARRSTACK_H
1.2 类实现文件 arrStack.cpp
//
// Created by mingm on 2019/3/27.
//
#include "arrStack.h"
#include <iostream>
using namespace std;
template <class T> arrStack<T>::arrStack(int capacity):m_pTop(-1),m_nStackLen(capacity)
{
arr = new T[capacity];
}
template <class T> arrStack<T>::~arrStack()
{
Clear();
delete [] arr;
arr = NULL;
}
template <class T> bool arrStack<T>::Empty() const
{
return m_pTop == -1;
}
template <class T> bool arrStack<T>::IsFull() const
{
return m_pTop == m_nStackLen - 1;
}
template <class T> void arrStack<T>::Clear()
{
m_pTop = -1;
}
template <class T> void arrStack<T>::Push(T &data)
{
if(IsFull())
{
// cout << "overflow !" << endl;
Expand();
}
arr[++m_pTop] = data;
}
template <class T> void arrStack<T>::Expand()
{
m_nStackLen = 2 * m_nStackLen;
T* temparr = new T[m_nStackLen];
for(int i = 0; i <= m_pTop; ++i)
{
temparr[i] = arr[i];
}
T* temp = arr;
arr = temparr;
temparr = temp;
delete [] temparr;
temparr = NULL;
}
template <class T> void arrStack<T>::Pop()
{
if(!Empty())
--m_pTop;
}
template <class T> T& arrStack<T>::GetTop() const
{
if(!Empty())
return arr[m_pTop];
throw "no elem!"; //抛出异常
}
template <class T> UINT arrStack<T>::GetLength() const
{
return m_nStackLen;
}
template <class T> void arrStack<T>::print()
{
cout << "----arrstack top----" << endl;
int i = m_pTop, j = m_pTop;
while(m_pTop != -1 && j >= 0)
{
cout << "No." << i-- << " elem " << arr[j--] << endl;
}
cout << "----arrstack bottom----" << endl;
}
1.3 测试程序及括号格式合法性检测 arrstack_testMain.cpp(练习了下try,catch)
//
// Created by mingm on 2019/3/27.
//
#include "arrStack.cpp"
#include <string>
#include <iostream>
using namespace std;
int main()
{
for(int i = 0; i < 20; ++i)
{
int k = 0;
arrStack<int> int_arr_stack(8);
int_arr_stack.print();
cout << "the capacity of stack is " << int_arr_stack.GetLength() << endl;
while(k < i)
{
int_arr_stack.Push(k);
++k;
}
try
{
cout << "top elem is " << int_arr_stack.GetTop() << endl;
}
catch(const char* str)
{
cout << str << endl;
}
cout << "the capacity of stack is " << int_arr_stack.GetLength() << endl;
int_arr_stack.print();
int_arr_stack.Clear();
cout << "---------------------------------" << endl;
}
cout << "以下测试一个字符串是否有非法格式的括号" << endl;
char conti = 'y', str;
while(conti == 'y'|| conti == 'Y')
{
bool legal = true;
arrStack<char> charstack(100);
cout << "please enter a string to check its brackets legal or not !" << endl;
while(cin.get(str) && str != '\n') //不断地获取输入的字符
{
if(str == '{' || str == '[' || str == '(') //遇到左括号不断地压栈
{
charstack.Push(str);
continue;
}
switch(str) //遇到非左括号
{
case '}':
try
{
if(charstack.GetTop() && charstack.GetTop() == '{') //栈不为空且栈顶与右括号匹配
charstack.Pop(); //删除左括号
else
legal = false; //直接遇上右括号,非法;or 栈顶与当前右括号不匹配
}
catch(const char* str) //若捕获try内的异常,没有元素在栈内,则遇到右括号,非法
{
legal = false;
}
break;
case ']':
try
{
if(charstack.GetTop() && charstack.GetTop() == '[')
charstack.Pop();
else
legal = false;
}
catch(const char* str)
{
legal = false;
}
break;
case ')':
try
{
if(charstack.GetTop() && charstack.GetTop() == '(')
charstack.Pop();
else
legal = false;
}
catch(const char* str)
{
legal = false;
}
break;
default:
break;
}
if(!legal)
break; //如果非法,不必循环了,直接退出
}
if(legal && charstack.Empty()) //如果合法,且符号都匹配了(栈为空)
cout << "legal string !" << endl;
else
{
cout << "illegal string !" << endl;
cin.ignore(10000,'\n'); //清除非法字符后面尚未get的字符
}
cout << "continue? y/n: " ;
cin >> conti;
cin.get();
}
return 0;
}
2.链式栈(链表存储,无需给定长度)
2.1 头文件 stack.h
/*
* 概述: 栈
* 作者: dongyaxing
* 版本: 1.0
* 创建时间:2019/3/25 20:47
* 修改者: liuyanfu
* 修改时间: 2019/3/25 21:14
*/
#ifndef _STACK_H
#define _STACK_H
template <class T>
struct SNode
{
T data;
SNode *pNext;
};
template <class T>
using StackNode = SNode<T>* ; //某些编译器不支持改语法
//template <class T> typedef SNode<T>* StackNode; //错误写法
typedef unsigned int UINT;
template <class T>
class Stack
{
public:
Stack(void); // 初始化栈
~Stack(void); // 析构栈
bool Empty() const; // 判断是否为空
void Clear(); // 则清空栈
StackNode<T> GetTop() const; // 得到栈顶元素
UINT GetLength() const; // 返回栈的长度
void Push(T &data); //往栈中压入数据
void Pop(); //将栈顶数据弹出
void print(); //自己加的接口,打印输出stack内容
private:
StackNode<T> m_pTop; // 栈顶元素
UINT m_nStackLen; // 栈长度
};
#endif //_STACK_H
2.2 类实现文件 stack.cpp
//
// Created by mingm on 2019/3/26.
//
#include "stack.h"
#include <iostream>
using namespace std;
template <class T> Stack<T>::Stack():m_pTop(NULL),m_nStackLen(0){}
template <class T> Stack<T>::~Stack() { Clear(); }
template <class T> bool Stack<T>::Empty() const
{
return m_nStackLen == 0;
}
template <class T> void Stack<T>::Clear()
{
while(m_pTop != NULL)
{
Pop();
}
}
template <class T> void Stack<T>::Push(T &data)
{
StackNode<T> newNode = new SNode<T>;
newNode->data = data;
newNode->pNext = NULL;
if(m_pTop == NULL)
{
m_pTop = newNode;
}
else
{
newNode->pNext = m_pTop;
m_pTop = newNode;
}
m_nStackLen++;
}
template <class T> void Stack<T>::Pop()
{
if(m_pTop != NULL)
{
StackNode<T> temp = m_pTop->pNext;
delete m_pTop;
m_pTop = temp;
m_nStackLen--;
}
}
template <class T> StackNode<T> Stack<T>::GetTop() const
{
return m_pTop;
}
template <class T> UINT Stack<T>::GetLength() const
{
return m_nStackLen;
}
template <class T> void Stack<T>::print()
{
cout << "----stack top----" << endl;
StackNode<T> temp = m_pTop;
size_t i = 0;
while(temp != NULL)
{
cout << "No." << ++i << " elem " << temp->data << endl;
temp = temp->pNext;
}
cout << "----stack bottom----" << endl;
}
2.3 链式栈 测试主程序
#include "stack.cpp"
#include <string>
#include <iostream>
using namespace std;
int main()
{
for(int i = 0; i < 10; ++i)
{
int nums = 0;
Stack<int> intstack;
if(intstack.Empty())
cout << "intstack is empty!" << endl;
cout << "after push nums: " << endl;
while(nums < i)
{
intstack.Push(nums);
nums++;
}
intstack.print();
intstack.Pop();
cout << "len of stack is " << intstack.GetLength() << endl;
if(intstack.GetTop())
cout << "top elem is " << intstack.GetTop()->data << endl;
if(!intstack.Empty())
cout << "intstack is not empty!" << endl;
intstack.print();
cout << "---------------------------------" << endl;
}
cout << "以下测试一个字符串是否有非法格式的括号" << endl;
char conti = 'y', str;
while(conti == 'y'|| conti == 'Y')
{
bool legal = true;
Stack<char> charstack;
cout << "please enter a string to check its brackets legal or not !" << endl;
while(cin.get(str) && str != '\n') //不断地获取输入的字符
{
if(str == '{' || str == '[' || str == '(') //遇到左括号不断地压栈
{
charstack.Push(str);
continue;
}
switch(str) //遇到非左括号
{
case '}':
if(charstack.GetTop() && charstack.GetTop()->data == '{') //栈不为空且栈顶与右括号匹配
charstack.Pop(); //删除左括号
else
legal = false; //直接遇上右括号,非法;or 栈顶与当前右括号不匹配
break;
case ']':
if(charstack.GetTop() && charstack.GetTop()->data == '[')
charstack.Pop();
else
legal = false;
break;
case ')':
if(charstack.GetTop() && charstack.GetTop()->data == '(')
charstack.Pop();
else
legal = false;
break;
default:
break;
}
if(!legal)
break; //如果非法,不必循环了,直接退出
}
if(legal && charstack.Empty()) //如果合法,且符号都匹配了(栈为空)
cout << "legal string !" << endl;
else
{
cout << "illegal string !" << endl;
cin.ignore(10000,'\n'); //清除非法字符后面尚未get的字符
}
cout << "continue? y/n: " ;
cin >> conti;
cin.get();
}
return 0;
}