/*
一、关于链式栈的约定,(目的是在C语言中描述方便)
1.定义:
(1)堆栈是一种先进后出的线性表;
(2)它只允许在表的一端(栈顶)进行入栈和出栈运算,另一端为栈底,入栈和出栈时不需
要改变栈底指针;
(3)运算受限的非循环单链表,它没有头结点,尾结点即栈底,栈底不存放有效数据,
只是指针域为NULL,链表中的插入删除操作在这里只能在栈顶进行。
(4)栈顶指针指向有效数据,并且可移动;栈底指针指向的结点不存有效数据,指针域
指向空NULL,永不移动。
2.创建链式栈时:
(1)需定义两个结构,一个用于描述结点(此结构跟链表结点对应的结构类似),另一个
用于描述是哪个栈(此结构包括栈顶和栈底指针);
(2)初创时,栈顶和栈底指针相等,都指向同一个结点,此结点不存放有效数据,指针域
指向NULL。入栈后,栈底指针不动。
3.入栈,出栈,编历,判断是否为空(链式栈不存在满问题),清空栈等操作。
*/
#include "LinkedStack.h"
//构建框架,即空栈
void linkedStackCreat(struct LinkedStack *pS)
{
pS->pTop =(struct LinkedStackNode *)malloc(sizeof(struct LinkedStackNode));
if( NULL == pS->pTop )
{
printf("initStack():malloc failed!\n");
exit(-1);
}
pS->pBottom = pS->pTop;
pS->pTop->pNext = NULL;//pS->pBottom->pNext = NULL;
/*
1. 即pS指向的对象的pTop成员,pTop成员指向的那个结点的指针域应该是空
2. 栈顶和栈底都共同指向一个结点,这个结点的指针域为NULL,即最后的结点pS->pBottom
以后就永远指向这个结点,不会移动,并且这个结点不存放有效数据,只是指针域为NULL
*/
return;
}
/*
1. 栈不存在满的问题,理论上大小可以是整个虚拟内存空间,所以没有返回值
2. 参数的含义:pS表示往哪个栈中压,val表示压入的值是多少
3. 压栈只能从最顶端压入
*/
void linkedStackPush(struct LinkedStack * pS,int val)
{
struct LinkedStackNode * pNew = NULL;
pNew =(struct LinkedStackNode *)malloc(sizeof(struct LinkedStackNode));
if( NULL == pNew )
{
printf("linkedStackPush():malloc failed!\n");
exit(-1);
}
pNew->data = val;
pNew->pNext = pS->pTop;//pS->Top不能改成pS->pBottom
pS->pTop = pNew;
return;
}
//遍历栈,并返回栈的深度
void traverseLinkedStack(struct LinkedStack * pS,int *LinkedStackDepth)
{
int i=0;
struct LinkedStackNode * p = pS->pTop;
while( p != pS->pBottom )
{
i++;
printf("data-%d is %d\n",i,p->data);
p = p->pNext;
}
*LinkedStackDepth = i;
return;
}
int linkedStackIsEmpty(struct LinkedStack * pS)
{
if( pS->pTop == pS->pBottom)
return 1;
else
return 0;
}
//把pS所指向的栈出栈一次,并把出栈的元素存入pVal形参所指向的变量中,如果出栈失败,返回false,否则返回true
int linkedStackPop(struct LinkedStack * pS,int *pVal)
{
struct LinkedStackNode *p=NULL;
if( 1 == linkedStackIsEmpty(pS) )
{
printf("linkedStackPop():This stack is empty!\n");
return 0;
}
p = pS->pTop;
*pVal = p->data;
pS->pTop = p->pNext;
/*
1,释放p指向的malloc所申请的那块内存(标记为可用),并不改变P指针
的值,即p的指向。
2,由于指针所指向的内存已经被释放,所以其它代码有机会改写其中的
内容,相当于该指针从此指向了自己无法控制的地方,也称为野指针;
3,为了避免失误,最好在free之后,将指针指向NULL。
*/
free(p);
p = NULL;
return 1;
}
//清空栈,使其变为空栈,框架还在
int clearLinkedStack(struct LinkedStack * pS)
{
if( 1 == linkedStackIsEmpty(pS) )
{
printf("clearLinkedStack():This stack is empty!\n");
return 0;
}
struct LinkedStackNode* p=pS->pTop;
struct LinkedStackNode* q=NULL;
while( p != pS->pBottom )
{
q = p->pNext;
free(p);
p = q;
}
pS->pTop = pS->pBottom;
return 1;
}
相关头文件:
#ifndef LINKEDSTACK_H
#define LINKEDSTACK_H
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
struct LinkedStackNode
{
int data;
struct LinkedStackNode *pNext;
};
struct LinkedStack
{
struct LinkedStackNode * pTop;
struct LinkedStackNode * pBottom;
};
void linkedStackCreat(struct LinkedStack *pS);
void linkedStackPush(struct LinkedStack * pS,int val);
void traverseLinkedStack(struct LinkedStack * pS,int *LinkedStackDepth);
int linkedStackIsEmpty(struct LinkedStack * pS);
int linkedStackPop(struct LinkedStack * pS,int *pVal);
int clearLinkedStack(struct LinkedStack * pS);
#endif