栈的链式存储结构
采用链式存储的栈称为链栈,所有操作都是在单链表的头部进行
带头结点的链栈实现
//栈的链式存储类型可描述为
//这里有两种方法
typedef struct Linknode
{
ElemType data; //数据域
struct Linknode *next //指针域
}*LiStack; //栈类型的定义
表示用它声明的数据,就是一个指针,比如LiStack a,a就是一个指针,要访问a的数据要用a->data的方式访问。
LiStack声明的变量是指针
typedef int ElemType;
struct Node { //单链表节点定义
ElemType data; //数据域
struct Node* next; //指针域
};
struct LinkStack { //链栈类型定义
struct Node* top;
};
typedef struct LinkStack* PLinkStack; //链栈类型的指针类型
带头结点的链栈定义
LinkStack CreateLinkStack(void)
{
LNode *s;int x;//定义指针
L=(LinkStack)malloc(sizeof(LNode));//创建头结点
if(L==NULL) //结点申请失败,返回空指针
{
return NULL;
}
L->top=NULL;//申请成功,栈顶指针为空
return L; //返回空链栈
}
链栈的判空操作
bool EmptyLinkStack(PLinkStack plstack)
{
return (L->top == NULL); //判断栈顶指针是否为空
}
链栈的判空操作
不用担心上溢这个问题
bool Push(PLinkStack plstack, ElemType e)
{
struct Node* p = (struct Node*)malloc(sizeof(struct Node));
if (p == NULL) //申请新节点空间失败
{
return false;
}
//不用判断栈是否已满
p->data = e;
p->next = L->top; //新节点连接到链栈栈顶指针之后,
L->top = p; //链栈栈顶指针指向新增节点
return true;
}
链栈的出栈操作
入栈不需要判空,出栈需要判空
栈不空时,先用e存储栈顶元素,再让栈顶指针指向栈中的第二个结点,最后释放第一个结点的内存空间。
bool Pop(PLinkStack plstack, ElemType* e)
{
struct Node* p;
if (L->top == NULL) //链栈为空,报错
{
return false;
}
*e = L->top->data; //e记录出栈的元素
p = L->top; //p指向第一个节点
L->top = p->next; //栈顶指针指向第二个接点
free(p); //释放出栈节点的内存空间
return true;
}
为什么是p->next是指向第二个结点
取链栈的栈顶元素
bool GetTopElem(PLinkStack plstack, ElemType* e)
{
if (L->top == NULL) //链栈为空,报错
{
return false;
}
*e = L->top->data; //e记录栈顶的元素
return true;
}
参考
链接: link.