1、栈的定义(逻辑结构)
栈是一种插入和删除操作都只能在表的同一端进行的线性表。这是一种受限的线性表,满足先进后出的原则(FILO),允许进行插入和删除操作的一端叫做栈顶(Top);另一端叫做栈底(Bottom)。
2、栈的顺序存储(物理结构)
设计时:栈顶放在数组的尾地址(效率高)
通过栈顶top
就可以完成一系列操作。开始将top = -1
#pragma once
#include<iostream>
using namespace std;
template<class T>
class LinerStack
{
public:
LinerStack(int LSMaxSize); //构造函数,创建空栈
~LinerStack(); //析构函数,删除栈
bool IsEmpty(); //判断栈是否为空,空返回true
bool IsFull(); //判断栈是否为满,满返回true
//int GetElementNumber(); //求栈中元素的个数
bool Push(const T& x); //进栈操作,在栈顶插入元素x,插入成功返回true
bool Top(T& x); //求栈顶元素的值放入x中
bool Pop(T& x); //出栈操作,从栈顶删除一个元素,并将该元素的值放入x
void OutPut(ostream& out)const;
private:
int top; //用来表示栈顶下标,初始为-1
int MaxSize; //栈中最多能存储的元素个数
T *element; //一维动态数组首地址
};
template<class T>
LinerStack<T>::LinerStack(int LSMaxSize)
{
MaxSize = LSMaxSize;
top = -1;
element = new T[LSMaxSize]; //开辟堆空间
}
template<class T>
LinerStack<T>::~LinerStack()
{
delete[] element;
}
template<class T>
bool LinerStack<T>::IsEmpty()
{
return top == -1;
}
template<class T>
bool LinerStack<T>::IsFull()
{
return top == MaxSize - 1;
}
//int GetElementNumber(); //求栈中元素的个数
template<class T>
bool LinerStack<T>::Push(const T& x)
{
if (IsFull()) //满栈返回false
return false;
else
{
top++;
element[top] = x;
return true;
}
}
template<class T>
bool LinerStack<T>::Top(T& x)
{
if (IsEmpty()) //空栈返回false
return false;
else
{
x = element[top];
return true;
}
}
template<class T>
bool LinerStack<T>::Pop(T& x)
{
if (IsEmpty()) //空栈返回false
return false;
else
{
x = element[top];
top--; //不需要将原位置的元素释放啥的,因为top指针下来之后,原来的栈顶原元素就访问不到了
//等再插入新元素时,就会把原来的覆盖掉
return true;
}
}
template<class T>
void LinerStack<T>::OutPut(ostream& out)const
{
for (int i = 0; i < top; i++)
{
out << element[i] << endl;
}
}
//重载插入运算符<< 全局函数
template<class T>
ostream& operator<<(ostream& out, const LinerStack<T>& x)
{
x.OutPut(out);
return out;
}
3、栈的链式存储(物理结构)
设计时:栈顶放在链表的头地址(效率高),放在尾部的话每次插入删除都需要从头遍历
#pragma once
#include<iostream>
using namespace std;
template<class T>
class LinkNode
{
template<class T>
friend class LinkStack;
public:
LinkNode() //构造函数
next = NULL; //每new一个结点时,先将他置空,串进链表之后才设next
private:
T data;
LinkNode<T>* next;
};
template<class T>
class LinkStack {
public:
LinkStack(); //构造函数,创建空栈
~LinkStack(); //析构函数,删除栈
bool IsEmpty() const; //判断栈是否为空
bool Push(const T& x); //在栈顶插入元素x
bool Top(T& x); //求栈顶元素的值放入x中
bool Pop(T& x); //从栈顶删除一个元素,并将该元素的值放入x中
void OutPut(ostream& out) const;
private:
LinkNode<T>* top; //指向栈顶结点的指针
int size; //栈中元素个数
};
template<class T>
LinkStack<T>::LinkStack()
{
top = NULL;
size = 0;
}
template<class T>
LinkStack<T>::~LinkStack()
{
T x;
while (top != NULL)
{
Pop(x);
}
}
template<class T>
bool LinkStack<T>::IsEmpty() const
{
return top == NULL;
}
template<class T>
bool LinkStack<T>::Push(const T& x) //这里x只是数据域
{
LinkNode<T>* p = new LinkNode<T>; //新建结点用于标记新插入的元素
if (p == NULL)
return false;
else
{
p->data = x;
p->next = top;
top = p;
size++;
return true;
}
}
template<class T>
bool LinkStack<T>::Top(T& x)
{
if (IsEmpty()) //空栈返回false
return false;
else
{
x = top->data;
return true;
}
}
template<class T>
bool LinkStack<T>::Pop(T& x)
{
LinkNode<T>* p = top; //记录待删除的结点
if (IsEmpty()) //空栈返回false
return false;
else
{
x = top->data;
top = top->next;
size--;
delete p;
return true;
}
}
template<class T>
void LinkStack<T>::OutPut(ostream& out)const
{
LinkNode<T>* p;
p = top;
for (int i = 0; i < size; i++)
{
out << p->data << endl;
p = p->next;
}
}
//重载插入运算符<< 全局函数
template<class T>
ostream& operator<<(ostream& out, const LinkStack<T>& x)
{
x.OutPut(out);
return out;
}
4、测试
#include<iostream>
using namespace std;
#include"LinerStack.h"
#include"LinkStack.h"
int main()
{
//LinerStack<int> s(5);
LinkStack<int> s;
s.Push(1);
s.Push(2);
s.Push(3);
s.Push(4);
s.Push(5);
int x;
s.Pop(x);
cout << x << endl;
s.Top(x);
cout << x << endl;
return 0;
}