一、栈的定义以及一些名词解释
栈(stack)又名堆栈,它是一种运算受限的线性表。其限制是仅允许在表的一端进行插入和删除运算
栈允许进行插入和删除操作的一端称为栈顶(top),另一端为栈底(bottom);栈底固定,而栈顶浮动;栈中元素个数为零时称为空栈。插入一般称为入栈(Push),删除则称为出栈(Pop)。
由于堆叠数据结构只允许在一端进行操作,因而按照先进后出(FILO, First In Last Out)的原理运作。
先进后出,个人理解类似于子弹上膛,先装入的子弹最后被打出。
二、对栈的常见操作
1、初始化栈(Init)
2、向栈里压入元素(Push)
3、得到栈顶元素内容(Pop)
4、统计栈内元素个数(GetCount)
5、清空栈(Clear)
6、得到栈顶元素(GetTop)
7、销毁栈(Destory)
8、判断栈是否为空(IsEmpty)
三、代码实现
1、想要对一个栈完成各种操作,首先你需要有一个栈,栈内需要有什么?
栈内有元素,还有指针,且最重要的元素为栈顶元素,我们只需要知道栈顶元素就能够通过它获得next,next->next, next->next->next, …
显然,我们需要一个结构体来封装我们这一个元素所具有的属性,也就是数据结构体,里面有元素的值和指针。
好了,那我们先来看一段代码
#include<stdio.h>
#include<stdlib.h>
typedef struct stack
{
int nValue;
struct stack*pNext;
}MyStack;
void Push (MyStack **pTop,int nNum)
{
MyStack *pTemp = NULL;
pTemp = (MyStack*)malloc(sizeof(MyStack));
pTemp->nValue = nNum;
pTemp->pNext = *pTop;
*pTop = pTemp;
}
int Pop(MyStack **pTop)
{
if(*pTop == NULL) return -1;
MyStack *pDel = *pTop;
int nNum = pDel->nValue;
*pTop = (*pTop)->pNext;
free(pDel);
pDel = NULL;
return nNum;
}
int main()
{
MyStack *pTop = NULL;
Push(&pTop,1);
Push(&pTop,2);
Push(&pTop,3);
Push(&pTop,4);
printf("%d\n",Pop(&pTop));
printf("%d\n",Pop(&pTop));
printf("%d\n",Pop(&pTop));
printf("%d\n",Pop(&pTop));
return 0;
}
这是对栈的一个Push和Pop操作
2、
(提前声明哦,有一些小伙伴不要看文字多就没有耐心了,其实我也这样,但是我就尽量用一些文字尽可能的让大家都懂,可能写的啰嗦,或者不太好,欢迎大家批评指正)
首先我们肯定的是我们上面这段代码是没有问题的,那让我们考虑接下来的其他操作该怎么实现,我们对每一个操作进行分析,在主函数里面定义了pTop,这就意味着只要程序没有结束以前,栈总是能用的,而我们的第7个操作栈的销毁是什么意思,是我们只要调用这个操作,栈就用不了,所以此时的销毁功能是没有办法完成的,说得更加直白一点那就是,栈用不了,就是pTop用不了,我们怎么才能决定pTop什么时候不能用呢,我们自己手动为pTop申请空间,并且初始化pTop,我们的初始化栈,其实也就是初始化栈顶pTop,在想要销毁栈的时候就free栈顶pTop,这样栈就用不了了,我们的目的也就达到了。
3、那我们要在哪里定义这个pTop,然后对它初始化进行操作呢?在其他函数里?在其他函数里定义,那我们在主函数里调用函数的时候该传什么样的参数呢?全局?也不行。那是否可以把pTop也封装在一个结构体里,想用的时候就初始化申请空间,然后指针调用进行操作,不想用就释放掉。
4、清空栈就是一直Pop,直到栈内元素个数为0,结束。判断栈是否为空也是看栈内元素个数是否为0,那么接下来最关键的就是统计栈内元素个数了,不可能count一次数一次,我们可以在结构体里除了pTop,在放一个nCount,计数变量,push的时候就++,Pop的时候就- -。
5、剩余代码实现
当然上述代码也要做出相应的改动。
#include<stdio.h>
#include<stdlib.h>
typedef struct data
{
int nValue;
struct data *pNext;
}MyStack;
typedef struct stack
{
int nCount;
MyStack *pTop;
}Stack;
void s_Init(Stack **pStack)
{
*pStack = (Stack *)malloc(sizeof(Stack));
(*pStack)->nCount = 0;
(*pStack)->pTop = NULL;
}
void s_Push (Stack *pStack,int nNum)
{
if(pStack == NULL)
{
printf("不存在\n");
return;
}
MyStack *pTemp = NULL;
pTemp = (MyStack*)malloc(sizeof(MyStack));
pTemp->nValue = nNum;
pTemp->pNext = pStack->pTop;
pStack->pTop = pTemp;
pStack->nCount++;
}
int s_Pop(Stack *pStack)
{
if(pStack == NULL) exit(1);
if(pStack->pTop == NULL) return -1;
MyStack *pDel = pStack->pTop;
int nNum = pDel->nValue;
pStack->pTop = pStack->pTop->pNext;
free(pDel);
pDel = NULL;
pStack->nCount--;
return nNum;
}
void s_Clear(Stack *pStack)
{
if(pStack == NULL) exit(1);
while(pStack->nCount != 0)
{
s_Pop(pStack);
}
}
void s_Destory(Stack **pStack)
{
s_Clear(*pStack);
free(*pStack);
*pStack = NULL;
}
int s_GetCount(Stack *pStack)
{
if(pStack == NULL) exit(1);
return pStack->nCount;
}
MyStack *s_GetTop(Stack *pStack)
{
if(pStack == NULL) exit(1);
return pStack->pTop;
}
int s_IsEmpty(Stack *pStack)
{
if(pStack == NULL) exit(1);
return pStack->nCount ?0:1;
}
int main()
{
Stack *pStack = NULL;
s_Init(&pStack);
s_Push(pStack,1);
s_Push(pStack,2);
s_Push(pStack,3);
s_Push(pStack,4);
printf("%d\n",s_Pop(pStack));
printf("%d\n",s_Pop(pStack));
printf("%d\n",s_Pop(pStack));
printf("%d\n",s_Pop(pStack));
s_Destory(&pStack);
s_Push(pStack,100);
return 0;
}