一,链栈的形式
链栈是指采用链式存储结构实现的栈。
通常用单链表来表示,链栈的结点结构与单链表的结构相同。
二,链栈的结构体表示
struct Node
{
Node *next; //下一结点
int data; //当前结点的数据域
};
图解:
类比单链表可以得出两个性质
- 链栈无上限,只要需要入栈,都可添加进去
- 链栈判断空的方法就是P是否等于NULL
当结构体作为形参时,应该如何定义函数
这个地方令我突然不会写单链表了。
- 首先看一种函数定义 void Init(Node *P); 可以看出如果这样传入实参P结点,则对于形参的赋值等一系列活动只在Init函数里面有用,主函数里面的实参并未发生变化。
- 再看第二种,void Init(Node &P);,此时若形参发生变化,则主函数里面的实参也就会发生变化。但是此时有另一个问题。在函数Init里面如何定义一个Node &类型的数据,与实参进行数据对接(这个方式我还没想明白,如果谁会可以留言或私信,进行讨论)
- 通过查资料,最后找到第三种方式,Node *Init(Node *P).此处将虽然形参依旧不影响实参,但是可以形参改变后通过返回,再与主函数中的实参对接。
(有什么更好的方法欢迎留言或私信讨论)
链栈的定义
Node *Init()
{
Node *A = new Node;
A = NULL; //将A赋值为空
return A;
}
新定义一个A,然后将A赋值为NULL,作为栈底,然后返回。
入栈
Node *Push(Node *P)
{
Node *A = new Node; //定义新节点
cout << "入栈值为:";
cin>>A->data;
A->next = P; //将A插入
P = A;
return P; //返回以P为头的链栈
}
先将实参传递进函数,经过赋值之后再返回。
出栈
Node *Pop(Node *P)
{
P = P->next; //P指向P的下一位
return P;
}
出栈后,P指向下一位(如需获得出栈前栈顶,可自行添加代码)
显示栈顶元素
void ShowTop(Node *P)
{
if (P != NULL) //判断栈是否为空
{
cout << "栈顶元素为:" << P->data << endl;
}
else
{
cout << "栈为空";
}
}
因为P指向的就是栈顶元素,所以当P不为空时,直接显示P->data就可以
遍历链栈
void ShowAll(Node *P)
{
if (P == NULL) //若不为空则继续
{
return;
}
else
{
cout << P->data; //显示当前栈顶元素
ShowAll(P->next); //将栈顶下一元素继续做形参递归
}
}
此处栈的遍历用的递归的方法:即每次显示栈顶元素,然后再将栈顶下一位作为形参继续遍历,知道栈为空
三,代码
#include<iostream>
using namespace std;
struct Node
{
Node *next;
int data;
};
Node *Init()
{
Node *A = new Node;
A = NULL;
return A;
}
Node *Push(Node *P)
{
Node *A = new Node;
cout << "入栈值为:";
cin>>A->data;
A->next = P;
P = A;
return P;
}
Node *Pop(Node *P)
{
P = P->next;
return P;
}
void ShowTop(Node *P)
{
if (P != NULL)
{
cout << "栈顶元素为:" << P->data << endl;
}
else
{
cout << "栈为空";
}
}
void ShowAll(Node *P)
{
if (P == NULL)
{
return;
}
else
{
cout << P->data;
ShowAll(P->next);
}
}
int main()
{
Node *P = Init();
P = Push(P);
ShowTop(P);
P = Push(P);
ShowTop(P);
P = Pop(P);
ShowTop(P);
P = Push(P);
P = Push(P);
ShowAll(P);
system("pause");
}