栈满足先进后出的功能,用于在很多场景,可以发挥意想不到的功能。
栈是一种特殊的线性表,因此可以通过线性链表来实现栈的功能。线性链表有顺序,和链式两种,这里选取链式链表实现栈(顺序请参考上一博客)。在链式链表实现栈模型,栈顶可以可以在链表的头部或尾部,用链表的尾部作为栈顶,入栈和出栈要遍历链表节点直到遍历到链表的尾部,过程复杂效率低下。但用链表的头部作为栈顶,入栈和出栈只用操作链表的首元素,不涉及到遍历链表,效率较高。因此,这里我们采用链表的头部做为栈顶。
详细讲解参照https://www.bilibili.com/video/av27904891/?p=1
本次使用工具为vs2017,作者水平有限,若有问题请指出。
栈头文件:Stack_Link_Cplus.h
#pragma once
typedef void StackData;
//定义栈节点数据类型
template<typename T>
struct StackNode
{
struct StackNode<T> *Next;
T data;
};
template<typename T>
class Stack_Link_Cplus
{
public:
Stack_Link_Cplus();
~Stack_Link_Cplus();
//清除栈
int ClearStack();
//获取栈的元素个数
int GetStackLen();
//元素压入栈
int PushStack(T _data);
//弹出元素
T PopStack();
//获取栈顶元素
T GetTopData();
private:
StackNode<T> stack;
int StackLen;
};
栈源文件:Stack_Link_Cplus.cpp
#include "pch.h"
#include "iostream"
#include "Stack_Link_Cplus.h"
using namespace std;
//默认的拷贝构造函数创建一个栈
template<typename T>
Stack_Link_Cplus<T>::Stack_Link_Cplus()
{
this->stack.Next = NULL;
this->StackLen = 0;
}
//析构函数,先释放开辟的内存,再清空指针和栈的长度
template<typename T>
Stack_Link_Cplus<T>::~Stack_Link_Cplus()
{
if (this->stack.Next == NULL)
{
this->stack.Next == NULL;
this->StackLen = 0;
}
else
{
StackNode<T> *current = this->stack.Next; //current指向0号节点
StackNode<T> *temp = this->stack.Next->Next; //temp指向1号节点
for (int i = 0; i < this->StackLen - 1; i++)
{
if (current != NULL)
{
delete current;
current = temp;
temp = current->Next;
}
}
this->stack.Next = NULL;
this->StackLen = 0;
}
}
//清除栈
template<typename T>
int Stack_Link_Cplus<T>::ClearStack()
{
int ret = 0;
if (this->StackLen <= 0)
{
cout << "Parameters is null :ClearStack() " << endl;
ret = -1;
return ret;
}
//数据类型转换
StackNode<T> *current = this->stack.Next; //current指向0号节点
StackNode<T> *temp = this->stack.Next->Next; //temp指向1号节点
for (int i = 0; i < this->StackLen - 1; i++)
{
if (current != NULL)
{
delete current;
current = temp;
temp = current->Next;
}
}
this->stack.Next = NULL;
this->StackLen = 0;
return ret;
}
//获取栈的元素个数
template<typename T>
int Stack_Link_Cplus<T>::GetStackLen()
{
int ret = 0;
if (this->StackLen < 0)
{
cout << "Stack is error :GetStackLen() " << endl;
ret = -1;
return ret;
}
return this->StackLen;
}
//元素压入栈
template<typename T>
int Stack_Link_Cplus<T>::PushStack(T _data)
{
int ret = 0;
StackNode<T> *datacopy = new StackNode<T>;
if (datacopy == NULL)
{
cout << "New StackNode Error :PushStack() " << endl;
ret = -1;
return ret;
}
//拷贝数据
datacopy->data = _data; //复杂数据类型,要重载=
datacopy->Next = NULL;
if (this->StackLen == 0) //空栈,第一次插入数据
{
this->stack.Next = datacopy;
datacopy->Next = NULL;
this->StackLen++;
}
else
{
datacopy->Next = this->stack.Next;
this->stack.Next = datacopy;
this->StackLen++;
}
return ret;
}
//弹出元素
template<typename T>
T Stack_Link_Cplus<T>::PopStack()
{
if (this->StackLen <= 0)
{
T item;
memset(&item,0,sizeof(T));
cout << "Stack hasn't element :PopStack() " << endl;
return item;
}
else if (this->StackLen == 1) //只有一个元素
{
T data = this->stack.Next->data;
this->stack.Next = NULL; //头指针为NULL
this->StackLen--;
return data;
}
else
{
T data = this->stack.Next->data;
this->stack.Next = this->stack.Next->Next; //头指针指向1号节点
this->StackLen--;
return data;
}
}
//获取栈顶元素
template<typename T>
T Stack_Link_Cplus<T>::GetTopData()
{
if (this->StackLen <= 0)
{
T item;
memset(&item, 0, sizeof(T));
cout << "Stack hasn't element :GetTopData() " << endl;
return item;
}
return this->stack.Next->data;
}
栈的测试源文件:Stack_Link_Cplus_Test.cpp
# include"pch.h"
# include"iostream"
#include "Stack_Link_Cplus.cpp"
# include"string"
using namespace std;
//person类
class person
{
public:
person()
{
}
person(string name,int age)
{
this->name = name;
this->age = age;
}
person(const person &obj)
{
this->name = obj.name;
this->age = obj.age;
}
person &operator=(person obj) //重载=
{
this->name = obj.name;
this->age = obj.age;
return *this;
}
~person()
{
}
public:
string name;
int age;
};
//测试int型数据
void test_int()
{
int a[10] = {0,1,2,3,4,5,6,7,8,9};
Stack_Link_Cplus<int> SLC;
int data = 0;
//测试入栈出栈
cout << "测试入栈和出栈" << endl;
SLC.PushStack(a[0]);
SLC.PushStack(a[1]);
SLC.PushStack(a[2]);
SLC.PushStack(a[3]);
SLC.PushStack(a[4]);
SLC.PushStack(a[5]);
data = SLC.PopStack();
cout << data << " " << endl;
data = SLC.PopStack();
cout << data << " " << endl;
data = SLC.PopStack();
cout << data << " " << endl;
data = SLC.PopStack();
cout << data << " " << endl;
data = SLC.PopStack();
cout << data << " " << endl;
data = SLC.PopStack();
cout << data << " " << endl;
data = SLC.PopStack();
cout << data << " " << endl;
//测试获取栈顶元素
cout << "测试获取栈顶元素" << endl;
data = SLC.GetTopData();
cout << data << " " << endl;
//测试清空栈
cout << "测试清空栈" << endl;
SLC.PushStack(a[3]);
SLC.PushStack(a[4]);
SLC.PushStack(a[5]);
SLC.ClearStack();
data = SLC.PopStack();
cout << data << " " << endl;
data = SLC.PopStack();
cout << data << " " << endl;
data = SLC.PopStack();
cout << data << " " << endl;
}
//测试person型数据
void test_person()
{
Stack_Link_Cplus<person> SLC;
person a0("pxzz",60), a1("wxxx", 61), a2("xrjj", 62), a3("hzww", 63), a4("wdff", 64), a5("lkoo", 65), a6("poii", 66), a7("hhhh", 67);
person data;
//测试入栈出栈
cout << "测试入栈和出栈" << endl;
SLC.PushStack(a0);
SLC.PushStack(a1);
SLC.PushStack(a2);
SLC.PushStack(a3);
SLC.PushStack(a4);
SLC.PushStack(a5);
data = SLC.PopStack();
cout << data.name << " " << data.age << endl;
data = SLC.PopStack();
cout << data.name << " " << data.age << endl;
data = SLC.PopStack();
cout << data.name << " " << data.age << endl;
data = SLC.PopStack();
cout << data.name << " " << data.age << endl;
data = SLC.PopStack();
cout << data.name << " " << data.age << endl;
data = SLC.PopStack();
cout << data.name << " " << data.age << endl;
data = SLC.PopStack();
cout << data.name << " " << data.age << endl;
//测试获取栈顶元素
cout << "测试获取栈顶元素" << endl;
data = SLC.GetTopData();
cout << data.name << " " << data.age << endl;
//测试清空栈
cout << "测试清空栈" << endl;
SLC.PushStack(a0);
SLC.PushStack(a1);
SLC.PushStack(a2);
SLC.ClearStack(); //清空栈
SLC.PushStack(a3);
SLC.PushStack(a4);
SLC.PushStack(a5);
data = SLC.PopStack();
cout << data.name << " " << data.age << endl;
data = SLC.PopStack();
cout << data.name << " " << data.age << endl;
data = SLC.PopStack();
cout << data.name << " " << data.age << endl;
}
int main()
{
test_int();
test_person();
system("pause");
return 0;
}