#include<stdio.h>

#include<malloc.h>

#include<stdlib.h>

//结点数据类型

typedef struct Node

{

int data;

struct Node *next;

}NODE,*PNODE;

//栈数据类型

typedef struct

{

PNODE top;

int cnt;

}Stack;

//想想看,为什么栈的数据结构是这样,我是这样思考的,如果你不这样写可以,

//那你必须造出一个计数的结点和链表头指针,计数变量可能是全局变量,这样数据过于离散,不利于组织和管理,我们将他们封装起来,利于维护

//也体现出了和面向对象封装的思想的相似性,当然这里不是面向对象了。

void initStack(Stack *);

void pushStack(Stack *,int);

void popStack(Stack *,int *);

bool stackEmpty(Stack *);

bool stackFull(Stack *,int *);

void main()

{

Stack stack;

//初始化栈

initStack(&stack);

//压栈

printf("开始压栈\n");

pushStack(&stack,2);

pushStack(&stack,3);

pushStack(&stack,4);

//出栈

printf("开始出栈\n");

int val;

popStack(&stack,&val);

popStack(&stack,&val);

popStack(&stack,&val);


}

void initStack(Stack *stack)

{

stack=(Stack *)malloc(sizeof(Stack));

if(NULL==stack)

{

printf("内存分配失败");

exit(-1);

}

stack->cnt=0;

stack->top=NULL    //这个地方有争议,到底指向一块内存,还是空,就看你是如何看待这个栈了。

}

void pushStack(Stack *stack,int val)

{

PNODE pnew=(PNODE)malloc(sizeof(NODE));

if(pnew==NULL)

{

printf("内存分配失败");

exit(-1);

}

//结点初始化

pnew->data=val;

pnew->next=NULL;

//开始压栈操作

//将栈top指针做为,新结点的后继,然后让新结点再次成为头指针。

pnew->next=stack->top;

stack->top=pnew;

stack->cnt++;

}

void popStack(Stack *stack,int *val)

{

if(stackEmpty(stack))

{

printf("栈已空,无法再出栈");

return;

}

*val=stack->top->data;

PNODE q=stack->top;

stack->top=stack->top->next;

stack->cnt--;

printf("%d  ",*val);

free(q);

printf("\n");


}

bool stackEmpty(Stack *stack)

{

if(stack->cnt==0)

return true;

else

return false;

}