数据结构——stack的实现

一、定义

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





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值