一、定义
栈stack是一种限定在仅仅只能在尾部进行插入删除的线性表。允许进行插入删除的一端叫做栈顶,而另一端就叫做栈底。
二、栈的分类
1. 顺序栈:所有操作的时间复杂度均为O(1);
2. 共享栈:两个栈共享一段空间向中间靠拢;
3. 链式栈:它的Push和Pop操作是头插法。
三、栈的模拟实现
在其中我还运用了类型萃取。
#include<cassert>
#include<iostream>
using namespace std;
struct _TrueType
{
bool Get()
{
return true;
}
};
struct _FalseType
{
bool Get()
{
return false;
}
};
template<class _Tp>
struct TypeTraits
{
typedef _FalseType _IsPODType;
};
template<>
struct TypeTraits<char>
{
typedef _TrueType _IsPODType;
};
template<>
struct TypeTraits<bool>
{
typedef _TrueType _IsPODType;
};
template<>
struct TypeTraits<int>
{
typedef _TrueType _IsPODType;
};
template<>
struct TypeTraits<unsigned char>
{
typedef _TrueType _IsPODType;
};
template<>
struct TypeTraits<short>
{
typedef _TrueType _IsPODType;
};
template<>
struct TypeTraits<unsigned short>
{
typedef _TrueType _IsPODType;
};
template<>
struct TypeTraits<unsigned int>
{
typedef _TrueType _IsPODType;
};
template<>
struct TypeTraits<long>
{
typedef _TrueType _IsPODType;
};
template<>
struct TypeTraits<unsigned long>
{
typedef _TrueType _IsPODType;
};
template<>
struct TypeTraits<long long>
{
typedef _TrueType _IsPODType;
};
template<>
struct TypeTraits<unsigned long long>
{
typedef _TrueType _IsPODType;
};
template<>
struct TypeTraits<double>
{
typedef _TrueType _IsPODType;
};
template<>
struct TypeTraits<long double>
{
typedef _TrueType _IsPODType;
};
template<>
struct TypeTraits<float>
{
typedef _TrueType _IsPODType;
};
class Date
{
public:
Date(int year = 1990, int month = 1, int day = 1);
friend ostream& operator<< (ostream& out, const Date& d);
Date operator+(int days);//返回一个值是因为不想改变当前的日期,
Date operator-(int days);
int operator-(const Date& d); //两个日期相减,两者差多少天。
Date& operator++(); //重载前置++。
Date operator++(int); //重载后置++。
Date& operator--(); //重载前置--。
Date operator--(int); //重载后置--。
bool operator<(const Date& d);//重载<
bool operator>(const Date& d);//重载>
bool operator<=(const Date& d);//重载<=
bool operator>=(const Date& d);//重载>=
bool operator==(const Date& d);//重载==
bool operator!=(const Date& d); //重载!=
private:
bool IsLeapYear(int year)
{
if ((year % 400 == 0) || (year % 4 == 0) && (year % 100 != 0))
{
return true;
}
else
{
return false;
}
}
int GetMonthInDay(int year, int month) //得到每一个月的天数。
{
char days[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
if (IsLeapYear(year) && (month == 2))
{
days[month]++;
}
return days[month];
}
private:
int m_year;
int m_month;
int m_day;
};
Date::Date(int year, int month, int day) :m_year(year), m_month(month), m_day(day)
{
if (!((year > 0) && ((month > 0) && (month < 13)) && ((day>0) && (day <= GetMonthInDay(year, month))))) //输入的日期不合法,将日期设置为默认值
{
m_year = 1900;
m_month = 1;
m_day = 1;
}
}
ostream& operator<< (ostream& out, const Date& d)
{
out << d.m_year << "--" << d.m_month << "--" << d.m_day;
return out;
}
Date Date:: operator+(int days)
{
if (days < 0)
{
return ((*this) - (0 - days));
}
Date temp(*this); //创建一个变量是因为在这个变量中操作要操作的东西,防止将原来的数据改变了。
temp.m_day += days; //将当前的天数+要加的天数。
while (temp.m_day > GetMonthInDay(temp.m_year, temp.m_month))
{
temp.m_day -= GetMonthInDay(temp.m_year, temp.m_month); //减去当前月的天数。
if (temp.m_month == 12)
{
temp.m_month = 1;
temp.m_year++;
}
else
{
temp.m_month++;
}
}
return temp;
}
Date Date:: operator-(int days)
{
if (days < 0)
{
return ((*this) + (0 - days));
}
Date temp(*this);
temp.m_day -= days;
while (temp.m_day <= 0)
{
if (temp.m_month == 1)
{
temp.m_month = 12;
temp.m_year--;
}
else
{
temp.m_month--;
}
temp.m_day += GetMonthInDay(temp.m_year, temp.m_month); //加上上一个月的天数。使得天数为真。
}
return temp; //返会一个临时变量,对真正的变量并未改动。
}
Date& Date:: operator++() //重载前置++。
{
(*this) = (*this) + 1; //将临时对象的值赋值给这个正在操作的对象。
return *this;
}
Date Date::operator++(int)//重载后置++。
{
Date temp(*this);
(*this) = (*this) + 1;
return temp;
}
Date& Date:: operator--() //重载前置--。
{
(*this) = (*this) - 1;
return *this;
}
Date Date:: operator--(int) //重载后置--。
{
Date temp(*this);
(*this) = (*this) - 1;
return temp;
}
int Date::operator-(const Date& d)
{
Date maxDate(*this);
Date minDate(d);
if (minDate > maxDate)
{
swap(minDate, maxDate);
}
int count = 0;
while (minDate < maxDate)
{
count++;
minDate++;
}
return count;
}
bool Date::operator<(const Date& d)//重载<
{
return ((m_year < d.m_year) || ((m_year == d.m_year) && (m_month < d.m_month))
|| ((m_year == d.m_year) && (m_month == d.m_month) && (m_day < d.m_day)));
}
bool Date:: operator>(const Date& d)//重载>
{
/*if (*this < d || *this == d)
{
return false;
}
else
{
return true;
}*/
return (!(*this < d) && !(*this == d));
}
bool Date:: operator<=(const Date& d)//重载<=
{
return !(*this>d);
}
bool Date:: operator>=(const Date& d)//重载>=
{
return !(*this < d);
}
bool Date:: operator==(const Date& d)//重载==
{
return (m_year == d.m_year && m_month == d.m_month && m_day == d.m_day);
}
bool Date:: operator!=(const Date& d) //重载!=
{
return !(*this == d);
}
template<class S>
class Stack
{
public:
Stack<S>()
: pdata(new S[5])
, size(0)
, capacity(5)
{}
bool Empty()const
{
return 0 == size;
}
void Push(const S& data)//栈的数据插入只能在栈顶进行
{
Checkapacity();//检测容量
pdata[size] = data;
size++;
}
void Pop()
{
assert(!Empty());
size--;
}
S& Top()
{
return pdata[size - 1];
}
size_t Size()
{
return size;
}
~Stack<S>()
{
if (pdata)
{
delete[] pdata;
pdata = NULL;
size = 0;
capacity = 0;
}
}
Stack<S>(const S& s)
: pdata[new S[s.capacity]]
, size(s.size)
, capacity(s.capacity)
{
cout << "Type" << ": " << typeid(S).name() << endl;
if (TypeTraits<S>::_IsPODType().Get())
{
memcpy(pdata, s.pdata, s.size);
}
else
{
for (int i = 0; i < size; i++)
{
pdata[i] = s.pdata[i];
}
}
}
Stack<S>& operator=(const S& s)
{
cout << "Type" << ": " << typeid(S).name() << endl;
if (this != &s)
{
if (capacity < s.size)
{
S *ptemp = new S[s.capacity];
delete pdata;
pdata = ptemp;
capacity = s.capacity;
}
if (TypeTraits<S>::_IsPODType().Get())
{
memcpy(pdata, s.pdata, s.size);
}
else
{
for (int i = 0; i < s.size; i++)
{
pdata[i] = s.pdata[i];
}
}
size = s.size;
}
return *this;
}
void Print()
{
for (size_t i = 0; i < size; i++)
{
cout << pdata[i] << " ";
}
cout << endl;
}
private:
S *pdata;
size_t size;//有效数据个数
size_t capacity;//栈的容量
void Checkapacity()//检测栈的容量——申请新的空间,拷贝原空间的数据,析构原来的空间
//(类型萃取分清数据是内置类型还是自定义类型)
{
cout << "Type" <<": "<<typeid(S).name() << endl;
if (size >= capacity)
{
S* ptemp = NULL;
ptemp = new S[capacity * 2];//申请新空间
if (TypeTraits<S>::_IsPODType().Get())
{
memcpy(ptemp, pdata, size);//memcpy可能会导致浅拷贝的问题,但是它的效率高于循环
}
else
{
for (size_t i = 0; i < size; i++)
{
ptemp[i] = pdata[i];//循环拷贝数据,虽然慢但是安全
}
}
delete[] pdata;//析构原来的空间
pdata = ptemp;
capacity = capacity * 2;
}
}
};
int main()
{
Date d1(2017, 1, 1);
Date d2(2017, 1, 2);
Date d3(2017, 1, 3);
Stack<Date> s;
/*s.Push(1);
s.Push(2);
s.Push(3);
s.Push(4);
s.Push(5);
s.Print();*/
s.Push(d1);
s.Push(d2);
s.Push(d3);
//s.Pop();
//s.Print();
/*int a=s.Top();
cout << a << endl;*/
Stack<Date> a(s);
a.Print();
/*Stack<int> a;
a = s;
a.Print();*/
system("pause");
return 0;
}
四、栈的应用
#include<stack>
#include<iostream>
using namespace std;
//1、括号匹配问题
//char a[] = "(())abc{[(])}"; // 左右括号次序匹配不正确
//char b[] = "(()))abc{[]}"; // 右括号多于左括号
//char c[] = "(()()abc{[]}"; // 左括号多于右括号
//char d[] = "(())abc{[]()}"; // 左右括号匹配正确
bool IsBracket(char c)//判断是不是括号,如果不是括号不用入栈
{
if (c == '(' || c == ')' ||
c == '[' || c == ']' ||
c == '{' || c == '}')
{
return true;
}
return false;
}
bool Match(char *str, size_t size)
{
std::stack<char> S;
for (size_t idx = 0; idx < size; idx++)
{
if (!IsBracket(str[idx]))
{
continue;
}
else
{
if (str[idx] == '(' || str[idx] == '[' || str[idx] == '{')
{
S.push(str[idx]);
continue;
}
if (S.empty())//相当于第一个是右括号入栈而不是左括号,第一次就匹配失败
{
cout << "右括号比左括号多" << endl;
return false;
}
char ctop = S.top();
if (((ctop == '(') && (str[idx] == ')')) ||
((ctop == '[') && (str[idx] == ']')) ||
((ctop == '{') && (str[idx] == '}')))
{
S.pop();
}
else
{
cout << "左右括号次序不匹配" << endl;
return false;
}
}
}
if (S.empty())//当所有的元素都扫描完毕,此时的栈已经为空,说明括号全部匹配
{
cout << "匹配成功" << endl;
return true;
}
else
{
cout << "左括号比右括号多" << endl;
return false;
}
}
int main()
{
char a[] = "(())abc{[(])}"; // 左右括号次序匹配不正确
char b[] = "(()))abc{[]}"; // 右括号多于左括号
char c[] = "(()()abc{[]}"; // 左括号多于右括号
char d[] = "(())abc{[]()}"; // 左右括号匹配正确
cout<<Match(a, strlen(a))<<endl;
cout<<Match(b, strlen(b))<<endl;
cout<<Match(c, strlen(c))<<endl;
cout<<Match(d, strlen(a))<<endl;
system("pause");
return 0;
}
#include<stack>
#include<iostream>
using namespace std;
//2.逆波兰表达式——把中缀表达式转换为后缀表达式
//12 * (3 + 4) - 6 + 8 / 2 == > 12 3 4 + *6 - 8 2 / +
enum Operator
{
ADD,
MUL,
SUB,
DIV,
DATA
};
struct Cell
{
Operator _opeator;
int _data;
};
int CalcRPN(Cell cell[], size_t size)
{
stack<int> S;
for (size_t idx = 0; idx < size; idx++)
{
if (cell[idx]._opeator == DATA)//如果是数字就入栈
{
S.push(cell[idx]._data);
}
else
{
int right = S.top();//每次取出栈顶的两个数字进行计算
S.pop();
int left = S.top();
S.pop();
switch (cell[idx]._opeator)
{
case ADD:
S.push(left + right);
break;
case MUL:
S.push(left * right);
break;
case SUB:
S.push(left - right);
break;
case DIV:
if (right == 0)
{
return -1;
}
S.push(left / right);
break;
default:
cout << "没有相关运算" << endl;
}
}
}
return S.top();
}
int main()
{
struct Cell cell[] = { { DATA, 12 }, { DATA, 3 }, { DATA, 4 }, { ADD, 0 }, { MUL, 0 },
{ DATA, 6 }, { SUB, 0 }, { DATA, 8 }, { DATA, 2 }, { DIV, 0 }, { ADD, 0 } };
int a = CalcRPN(cell, sizeof(cell) / sizeof(cell[0]));
cout << a << endl;
system("pause");
return 0;
}