简单实现一个栈

用单向动态链表实现栈

存在整个程序只能定义一个相同类型的栈的问题(静态数据成员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;
}

输出:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值