数据结构——stack的实现

来源:互联网 发布:四川广电网络 宽带 编辑:程序博客网 时间:2024/06/06 10:00

一、定义

       栈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;}




0 0