栈是一种常见的数据结构,它具有后进先出(LIFO)的特性,即最后入栈的元素最先出栈。
栈的顺序存储是指使用数组来实现栈的存储结构。在顺序存储中,栈的底部对应数组的起始位置,栈的顶部对应数组的末尾位置。当元素入栈时,将元素放置在栈顶位置,栈顶指针向上移动;当元素出栈时,将栈顶元素移除,并将栈顶指针向下移动。
栈的链式存储是指使用链表来实现栈的存储结构。在链式存储中,栈中的每个元素被视为链表的节点,节点包含一个数据域和一个指向下一个节点的指针。入栈操作将新元素插入链表的头部,将链表的头指针指向新的节点;出栈操作将头部的节点删除,并将链表的头指针指向下一个节点。
由于栈的运算方式受限,一般来说顺序栈的应用更加广泛。
顺序存储
栈的存储结构
template <typename T>
class MyStack
{
public:
MyStack(int _stack_capacity = 8);//默认参数在声明处说明即可
~MyStack();
void Push(const T& _data);//入栈
void Pop();//删除
T& Top();//返回栈顶数据
bool Empty();//判断栈是否为空
int Size();//返回栈的大小
void print();
private:
T* stack;//栈指针
int top;//栈顶位置
int stack_capacity;//栈的大小
void ChangeSize();//栈的扩容函数
};
顺序栈的方法
//构造函数和析构函数
template <typename T>
MyStack<T>::MyStack(int _stack_capacity):stack_capacity(_stack_capacity)
{
stack = new T[stack_capacity];//生成一个大小为stack_capacity的栈
top = -1;
}
template <typename T>
MyStack<T>::~MyStack()
{
delete[] stack;
}
//入栈
template <typename T>
void MyStack<T>::Push(const T& _data)
{
if (top == stack_capacity - 1)
{//判断栈是否满了
ChangeSize();//扩容
}
stack[++top] = _data;
}
//出栈
template <typename T>
void MyStack<T>::Pop()
{
if (!Empty())
top--;
else
exit(1);
}
//获取栈顶数据
template <typename T>
T& MyStack<T>::Top()
{
if (!Empty())
return stack[top];//非空就返回栈顶数据
else
exit(1);
}
//判空
template <typename T>
bool MyStack<T>::Empty()
{
if (top < 0)
return true;
else
return false;
}
//栈的大小
template <typename T>
int MyStack<T>::Size()
{
return (top + 1);
}
template<typename T>
void MyStack<T>::print()
{
while (top != 0)
{
cout << stack[top];
top--;
}
cout << stack[top];
}
顺序栈的扩容
由于顺序栈使用数组进行定义,在初始化时无法像链栈一样动态分配空间,当空间用完时只能手动扩容
扩容函数
template <typename T>
void MyStack<T>::ChangeSize()
{
cout << "栈扩容" << endl;
int size = stack_capacity * 2;//栈容量扩大1倍
T* tmp = new T[size];//1.申请一块原来2倍大小的空间。
copy(stack, stack + stack_capacity, tmp);//2.将栈中的数据赋值到新的内存空间
delete[] stack;//3.删除老的空间
stack = tmp;//4.stack指向新地址
stack_capacity = size;//5.改变stack_capacity大小
}
大体思路是分配一块空间使这块空间是以前的两倍(更加高效),然后将原来的栈中的数据复制到新的空间中去,将原来的栈指针指向新分配的空间。
栈的应用(进制转化)
int main()
{
MyStack<int>Q;
int data;
cout << "请输入你要转化的数据" << endl;
cin >> data;
while (data)
{
Q.Push(data % 2);
data /= 2;
}
Q.print();
}
当数据转化后长度大于预设(8)会自动扩容如下图
链栈
链栈的存储格式
template<typename T>
class template_class
{
private:
T data;
public:
template_class<T>*top;
template_class<T>* next;
public:
template_class();
~template_class();
public:
void print();
void push(T data);
void pop(T data);
void Change(T data);
void Search(T data);
};
链栈的方法
template<typename T>
inline template_class<T>::template_class()
{
this->next = NULL;
this->top = NULL;
}
template<typename T>
inline template_class<T>::~template_class()
{
if (top == NULL)
{
return;
}
else
{
template_class<T>* pcurrent = top;
template_class<T>* curr = NULL;
while (pcurrent->next != NULL)
{
curr = pcurrent;
pcurrent = pcurrent->next;
delete curr;
curr = NULL;
}
delete pcurrent;
pcurrent = NULL;
}
}
template<typename T>
inline void template_class<T>::print()
{
if (top == NULL)
{
cout << "没有数据" << endl;
return;
}
else
{
template_class<T>* pcurrent = top;
while (pcurrent->next != NULL)
{
cout << pcurrent->data << endl;
pcurrent = pcurrent->next;
}
cout << pcurrent->data << endl;
return;
}
}
template<typename T>
inline void template_class<T>::push(T data)
{
template_class<T>* pcurrent = new template_class<T>;
pcurrent->data = data;
if (top == NULL)
{
top = pcurrent;
}
else
{
pcurrent->next = top;
top = pcurrent;
}
}
template<typename T>
inline void template_class<T>::pop(T data)
{
if (top == NULL)
{
return;
}
if (top != NULL && top->next == NULL)
{
data = top->data;
delete top;
top = NULL;
}
if (top != NULL && top->next != NULL)
{
template_class<T>* curr = top;
top = top->next;
data = curr->data;
}
}
template<typename T>
inline void template_class<T>::Change(T data)
{
template_class<T>* pcurrent = top;
if (top == NULL)
{
cout << "没有数据" << endl;
return;
}
else
{
while (pcurrent->data != data)
{
pcurrent = pcurrent->next;
}
if (pcurrent->next == NULL && pcurrent->data != data)
{
cout << "没有目标数据" << endl;
return;
}
else
{
T da;
cout << "请输入数据" << endl;
cin >> da;
pcurrent->data = da;
cout << "更改成功" << endl;
return;
}
}
}
template<typename T>
inline void template_class<T>::Search(T data)
{
/*template_class<T>* pcurrent = top;
while (pcurrent->data != data)
{
pcurrent = pcurrent->next;
}
if (pcurrent->next == NULL && pcurrent->data != data)
{
cout << "没有目标数据" << endl;
return;
}
if (pcurrent->next == NULL && pcurrent->data == data)
{
cout << pcurrent->data << endl;
return;
}
cout << pcurrent->data << endl;*/
template_class<T>* pcurrent = top;
if (top == NULL)
{
cout << "没有数据" << endl;
return;
}
else
{
while (pcurrent->data != data)
{
pcurrent = pcurrent->next;
}
if (pcurrent->next == NULL && pcurrent->data != data)
{
cout << "没有目标数据" << endl;
return;
}
else
{
cout << pcurrent->data << endl;
}
}
}
总的来说链栈就是运算受限的链表(一般是单链表,也可以使用双向链表实现),它的操作比较简单,但是存储密度很小,且发挥不出链表该有的灵活性,因此不是很常见。