一.栈的定义:
在刷算法题时和解决业务问题时,经常会使用到栈的思想,那么这个栈到底是什么东西呢?其实栈(stack)就是一种特殊的线性表的数据结构,线性表可以任意操作结构中的数据,而且栈不一样,是一种有限制的线性表,我们能操作的只有栈顶元素。好比弹夹子弹装弹以及桶装水的过程,我们只能控制最上面的元素。核心遵循的原则思想就是:“先进后出”/“后进先出”。和线性表一样,也有顺序栈和链式栈两种存储。不同的是,由于栈的限制,一般的操作只有入栈与出栈。
二.栈的各自操作:
一般的,栈底是固定不变的,而栈顶是活动,为了方便,通常会使用一个变量去描述这个栈顶top,借用“栈顶指针”去称呼top变量。需要注意的是,top并不是一个指针变量,一些教材这里只是为了称呼方便。
2.1 顺序栈的操作
#include<stdio.h>
#include<stdlib.h>
#define maxsize 10
typedef struct{
int *data;
int top;//栈顶“指针”
}sstack;
// int isFull(sstack *s);
// int isEmpty(sstack *s);
sstack initStack()
{
sstack s;
s.data=(int*)malloc(sizeof(int)*maxsize);
if(s.data==NULL)
{
printf("空间分配失败\n");
}
s.top=-1;//top标记的是真正栈顶元素的位置
//s.top=0;//top标记的是真正栈顶元素上面一个的位置
return s;
}
//判满
int isFull(sstack *s)
{
if(s->top==maxsize-1)//if(s->top==maxsize)
{
return 1;
}
return 0;
}
//入栈
void Push(sstack *s,int k)
{
if(isFull(s)==1)
{
printf("栈满,不能入栈\n");
}
else
{
s->top++;//s->data[s->top]=k;
s->data[s->top]=k;//s->top++
//或s->data[++s->top]=k;//s->data[s->top++]=k;
}
}
//判空
int isEmpty(sstack *s)
{
if(s->top==-1)//if(s->top==0)
{
return 1;
}
return 0;
}
//出栈
void Pop(sstack *s)
{
if(isEmpty(s)==1)
{
printf("栈空,不能出栈\n");
}
else
{
s->top--;
}
}
//得到栈顶数据
int getTop(sstack s)
{
if(isEmpty(&s)==1)
{
printf("栈空,没有数据\n");
return -1;//特殊值
}
return s.data[s.top];//return s.data[s.top-1]
}
int main()
{
sstack s=initStack();
//传入指针进行函数调用
Push(&s,1);
printf("%d\n",getTop(s));
Push(&s,2);
Push(&s,3);
printf("%d\n",getTop(s));
Pop(&s);
printf("%d\n",getTop(s));
return 0;
}
2.2 链式栈的操作
链栈的各种操作是基于带头结点的单链表实现的,这里选用头插法进行栈顶元素的操作:
#include<stdio.h>
#include<stdlib.h>
//基于带头结点的单链表实现
typedef struct StackNode{
int data;
struct StackNode* next;
}sstackNode,*linkstack;
//初始化一个带头结点的栈
linkstack initstack()
{
sstackNode* s=(sstackNode*)malloc(sizeof(sstackNode));
if(s==NULL)
{
printf("空间分配失败\n");
}
s->next==NULL;
// return s;
}
//入栈(头插法)
linkstack Push(linkstack top,int k)
{
sstackNode* s=(sstackNode*)malloc(sizeof(sstackNode));
if(s==NULL)
{
printf("空间分配失败\n");
return top;
}
s->data=k;
s->next=top->next;
top->next=s;
return top;
}
//判空
int isEmpty(linkstack top)
{
if(top->next==NULL){
return 1;
}
return 0;
}
//出栈
linkstack Pop(linkstack top)
{
if(isEmpty(top)==1)
{
printf("栈空,不能出栈\n");
}
else
{
sstackNode *p=top->next;
top->next=p->next;
free(p);
p=NULL;
}
return top;
}
int getTop(linkstack top)
{
if(isEmpty(top)==1)
{
printf("栈空,没有数据\n");
return -1;//特殊值
}
else
{
return top->next->data;
}
}
int main()
{
linkstack top=initstack();
top=Push(top,1);
printf("%d\n",getTop(top));
top=Push(top,2);
top=Push(top,3);
printf("%d\n",getTop(top));
top=Pop(top);
printf("%d\n",getTop(top));
return 0;
}
二.总结:
栈的基本内容并不多,just-so-so,重点在于如何应用去解决问题,要把握这种“先进后出”/“后进先出”思想,多加练习,才能真正掌握。