用单向动态链表实现栈
存在整个程序只能定义一个相同类型的栈的问题(静态数据成员stack的问题及解决方案)
代码先行,说明随后就到
template<class Type> //定义模板类
class Stack
{
private:
Type data;
Stack* next; //指向下一个节点的指针
static Stack* head; //指向表头的指针
public:
Stack() :next(NULL) {}
~Stack() {
delete next;
}
void push(Type);
Type top();
void pop();
};
template<class Type>
Stack<Type>* Stack<Type>::head = NULL;//初始化表头指针
template<class Type>
void Stack<Type>::push(Type data) {
Stack* temp=new Stack(); //新建节点
temp->data = data; //储存数据
temp->next = head; //将新建节点连接到表头
head = temp; //更新表头指针
}
template<class Type>
Type Stack<Type>::top() {
if (head) return head->data;//确保表头指针为空时不会
return Type(0); //导致程序异常结束
}
template<class Type>
void Stack<Type>::pop() {
if(head) head = head->next;//确保表头指针为空时不会
} //导致程序异常结束
首先我们想要实现类似函数递归调用那样的,到达边界条件后能够逐层返回功能,就相当于我们储存砖头时一块一块的往上堆叠,当需要用时我们又是一块一块的拿下来用。
所以我们要干的就是将数据一个一个的往上堆叠,当需要用时一个一个的拿下来用,实现这样的功能的办法很多,比如单向动态链表。
首先我的大脑中会有一个层层往上堆叠东西,然后某一时刻又一层层的拿下来的画面,好像单向动态链表可以实现这样的东西。
struct temp
{
某种类型数据
temp* next;
};
貌似有一定的问题,我们将数据一个个的连接到表尾,可以实现像一层层往上堆叠东西的功能,但问题出在怎么将东西拿下来,由于我的动态链表是单向的,意味着我一个个的连接到表尾后无法返回上一个值。
当然你可以弄一个双向的链表解决这个问题,或者用一个指针指向表头,每次从表头往后遍历,貌似这两种方法都比较麻烦,那如果我们将数据连接到表头呢,好像解决了这个问题,我们将数据一个个的连接到表头,指针总是指向表头,需要时就从表头一个个的取出。
接下来就是实现环节了
定义单向动态链表:
class Stack
{
private:
int data;
Stack* next;
};
然后我们还需要一个指向表头的指针,我们自然是希望所有的对象共有这一个指向表头的指针,而不是每一个对象都有一个表头指针,那样岂不乱套了,我到底用哪个表头指针,于是:
class Stack
{
private:
int data;
Stack* next;
static Stack* head;
};
接下来应该初始化这些值:
Stack() :next(NULL) {}
但是静态数据成员,也就是我们定义的表头指针head无法用列表初始化的方式设初值,所以:
class Stack
{
private:
int data;
Stack* next;
static Stack* head;
public:
Stack() :next(NULL) {}
};
Stack* Stack::head = NULL;
接下来我们的栈应该要有将数据层层堆上去的功能,那我们需要一个函数来实现:
class Stack
{
private:
int data;
Stack* next;
static Stack* head;
public:
Stack() :next(NULL) {}
void push(int);
};
我们着手定义这样的一个函数:
void Stack::push(int data) {
Stack* temp=new Stack();//新建节点储存数据
temp->data = data; //储存数据
temp->next = head; //将新建的节点连接到表头
head = temp; //更新表头指针
}
这里我们用new的方式新建了一个Stack对象,那我们应该在不用这个对象的时候删除它:
class Stack
{
private:
int data;
Stack* next;
static Stack* head;
public:
Stack() :next(NULL) {}
~Stack() {
delete next;
}
void push(int);
};
之后我们要能够拿到顶部的数据:
class Stack
{
private:
int data;
Stack* next;
static Stack* head;
public:
Stack() :next(NULL) {}
~Stack() {
delete next;
}
void push(int);
int top();
};
于是我们开始定义这个函数的实现:
int Stack::top() {
return head->data;
}
但是,如果表头指针,也就是head为空的话,这个函数会导致程序异常结束,因为,head为空,哪来的数据data,也许我们应该加一个判断:
int Stack::top() {
if (head) return head->data;
return -99999999;
}
之后,我们还希望把当初一层层放上去的数据又一层层的拿下来:
class Stack
{
private:
int data;
Stack* next;
static Stack* head;
public:
Stack() :next(NULL) {}
~Stack() {
delete next;
}
void push(int);
int top();
void pop();
};
定义这样的一个功能:
void Stack::pop() {
head = head->next;
}
还是表头指针可能出问题,如果表头指针为空,哪来的下一个next,那我们还是要一个判断:
void Stack::pop() {
if(head) head = head->next;
}
貌似我们已经完成了
class Stack
{
private:
int data;
Stack* next;
static Stack* head;
public:
Stack() :next(NULL) {}
~Stack() {
delete next;
}
void push(int);
int top();
void pop();
};
Stack* Stack::head = NULL;
void Stack::push(int data) {
Stack* temp=new Stack();
temp->data = data;
temp->next = head;
head = temp;
}
int Stack::top() {
if (head) return head->data;
return -99999999;
}
void Stack::pop() {
if(head) head = head->next;
}
如果我们要储存的不是int型数据呢,
也许我们应该要使用类模板:
template<class Type>
class Stack
{
private:
Type data;
Stack* next;
static Stack* head;
public:
Stack() :next(NULL) {}
~Stack() {
delete next;
}
void push(Type);
Type top();
void pop();
};
template<class Type>
Stack<Type>* Stack<Type>::head = NULL;
template<class Type>
void Stack<Type>::push(Type data) {
Stack* temp=new Stack();
temp->data = data;
temp->next = head;
head = temp;
}
template<class Type>
Type Stack<Type>::top() {
if (head) return head->data;
return Type(0);
}
template<class Type>
void Stack<Type>::pop() {
if(head) head = head->next;
}
测试走一波:
struct temp
{
int t;
temp(int a) :t(a) {}
temp(void) {}
};
int main() {
Stack<temp> stack;
cout << stack.top().t << endl;//测试head为空时
for (int i = 1; i < 5; ++i) {
temp* test = new temp(i);
stack.push(*test); //测试入栈
cout << stack.top().t << endl;//测试栈顶元素
}
for (int i = 1; i < 5; ++i) {
stack.pop(); //测试出栈
cout << stack.top().t << endl;//测试栈顶元素
}
return 0;
}
输出: