定义:栈是限定在表尾进行插入和删除操作的线性表
允许插入和删除的一段称为栈顶(top),另一端称为栈底(top)。栈是后进先出(Last In First Out)的线性表,简称LIFO结构。
一、顺序栈
当栈存在一个元素时,top等于0,因此通常把栈空的判定条件设定为top=-1。
顺序栈的动态数组实现:
//顺序栈,动态数组实现,感觉用的较少。和静态数组基本一样
#include<stdio.h>
#define true 1
#define false 0
#define STACK_INIT_SIZE 20
typedef int bool;
typedef struct SequenceStack
{
int *data;
int top;//用于栈顶指针。当栈为空时top=-1,栈满时top=MAXSIZE-1
}SqStack;
//初始化栈
bool InitStack(SqStack *s)
{
s->data = (int*)malloc(sizeof(int)*STACK_INIT_SIZE);
if (!s->data)
exit(-1);
s->top = -1;
return 1;
}
//栈空判断,空返回1,非空返回0
bool StackEmpty(SqStack *s)
{
if (s->top == -1)
return true;
else
return false;
}
//栈的长度
int StackLength(SqStack *s)
{
return s->top + 1;
}
//返回栈顶元素
bool StackGetTop(SqStack *s, int *val)
{
if (s->top == -1)
return false;
*val = s->data[s->top];
return true;
}
//入栈
//入栈时判断栈满
bool Push(SqStack *s, int val)
{
if (s->top == STACK_INIT_SIZE - 1)
return false;
s->top++;
s->data[s->top] = val;
return true;
}
//出栈
//出栈,判断栈空
bool Pop(SqStack *s, int *val)
{
if (s->top == -1)
return false;
*val = s->data[s->top];
s->top--;
return true;
}
//清栈
void StackClear(SqStack *s)
{
s->top = -1;
}
//销毁栈
void StackDestroy(SqStack *s)
{
free(s->data);
s->data = NULL;
s->top = -1;
}
//遍历栈
void StackTraverse(SqStack *s)
{
for (int i = 0; i <= s->top; i++)
{
printf("%d ", s->data[i]);
}
printf("\n");
}
int main(void)
{
SqStack s;
//初始化栈
InitStack(&s);
//初始化栈之后,判断栈是否为空
printf("初始化栈之后,判断栈是否为空:%d\n", StackEmpty(&s));
printf("初始化栈之后,求栈的长度\:%d\n", StackLength(&s));
//入栈几个元素
Push(&s, 4);
Push(&s, 1);
Push(&s, 7);
Push(&s, 2);
//遍历栈
printf("入栈之后,遍历栈\n");
StackTraverse(&s);
//出栈
int val;
Pop(&s, &val);
printf("出栈元素为:%d\n", val);
//遍历栈
printf("出栈之后,遍历栈\n");
StackTraverse(&s);
//判断栈是否为为空
printf("栈空否?%d\n", StackEmpty(&s));
printf("栈长:%d\n", StackLength(&s));
//获取栈顶元素
StackGetTop(&s, &val);
printf("栈顶元素为:%d\n", val);
//清栈
StackClear(&s);
printf("清栈之后,栈空否?%d\n", StackEmpty(&s));
return 0;
}
顺序栈的静态数组实现:
//栈的顺序存储结构,静态数组实现。感觉用的较多
#include<stdio.h>
#define true 1
#define false 0
#define MAXSIZE 20
typedef int bool;
typedef struct SequenceStack
{
int data[MAXSIZE];
int top;//用于栈顶指针。当栈为空时top=-1,栈满时top=MAXSIZE-1
}SqStack;
//初始化栈
bool InitStack(SqStack *s)
{
s->top = -1;
return 1;
}
//栈空判断,空返回1,非空返回0
bool StackEmpty(SqStack *s)
{
if (s->top == -1)
return true;
else
return false;
}
//栈的长度
int StackLength(SqStack *s)
{
return s->top + 1;
}
//返回栈顶元素
bool StackGetTop(SqStack *s, int *val)
{
if (s->top == -1)
return false;
*val = s->data[s->top];
return true;
}
//入栈
//入栈时判断栈满
bool Push(SqStack *s, int val)
{
if (s->top == MAXSIZE - 1)
return false;
s->top++;
s->data[s->top] = val;
return true;
}
//出栈
//出栈,判断栈空
bool Pop(SqStack *s, int *val)
{
if (s->top == -1)
return false;
*val = s->data[s->top];
s->top--;
return true;
}
//清栈
void StackClear(SqStack *s)
{
s->top = -1;
}
//遍历栈
void StackTraverse(SqStack *s)
{
for (int i = 0; i <= s->top; i++)
{
printf("%d ", s->data[i]);
}
printf("\n");
}
int main(void)
{
SqStack s;
//初始化栈
InitStack(&s);
//初始化栈之后,判断栈是否为空
printf("初始化栈之后,判断栈是否为空:%d\n", StackEmpty(&s));
printf("初始化栈之后,求栈的长度\:%d\n", StackLength(&s));
//入栈几个元素
Push(&s, 4);
Push(&s, 1);
Push(&s, 7);
Push(&s, 2);
//遍历栈
printf("入栈之后,遍历栈\n");
StackTraverse(&s);
//出栈
int val;
Pop(&s, &val);
printf("出栈元素为:%d\n", val);
//遍历栈
printf("出栈之后,遍历栈\n");
StackTraverse(&s);
//判断栈是否为为空
printf("栈空否?%d\n", StackEmpty(&s));
printf("栈长:%d\n", StackLength(&s));
//获取栈顶元素
StackGetTop(&s, &val);
printf("栈顶元素为:%d\n", val);
//清栈
StackClear(&s);
printf("清栈之后,栈空否?%d\n", StackEmpty(&s));
return 0;
}
二、链栈
在链栈中,一般不需要头结点,用top指针代替了链表中的头指针。注意链栈中元素之间指针的指向,跟链表是反过来的。
入栈:
对于链栈的入栈push操作,假设要入栈结点为s,元素值为e,top为栈顶指针。
出栈:
出栈p结点。
示意图:
链栈实现:
//栈,不带头结点
#include<stdio.h>
#define true 1
#define false 0
typedef int bool;
typedef struct StackNode
{
int data;
struct node *next;
}StackNode,*PStackNode;
typedef struct LinkStack
{
int count;
PStackNode top;
}LinkStack,*PLinkStack;
//初始化栈,成功返回1,失败返回0
void InitStack(PLinkStack s)
{
s->top = NULL;
s->count = 0;
return;
}
//入栈,成功返回1,失败返回0
bool Push(PLinkStack s,int val)
{
PStackNode pNew = (PStackNode)malloc(sizeof(StackNode));
if (pNew == NULL)
{
return 0;
}
pNew->data = val;
pNew->next = s->top;
s->top = pNew;
s->count++;
return 1;
}
//出栈,成功返回1,失败返回0
bool Pop(PLinkStack s, int *val)
{
if (s->top == NULL)
{
return 0;//栈空,出栈失败
}
PStackNode p = s->top;
*val = s->top->data;
s->top = s->top->next;
free(p);
s->count--;
return 1;
}
//遍历
void StackTraverse(PLinkStack s)
{
PStackNode p = (PStackNode)malloc(sizeof(StackNode));
p = s->top;
while (p)
{
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
//获取栈顶元素
bool GetTop(PLinkStack s, int *val)
{
if (s->top == NULL)
{
return 0;
}
*val = s->top->data;
return 1;
}
//栈空判断
bool StackEmpty(PLinkStack s)
{
if (s->top == NULL)
return 1;
else
return 0;
}
//栈长
int StackLength(PLinkStack s)
{
return s->count;
}
//清栈
void ClearStack(PLinkStack s)
{
PStackNode p = s->top;
while (p)
{
s->top = p->next;
free(p);
p = s->top;
}
s->count = 0;
}
int main(void)
{
LinkStack s;
//初始化栈
InitStack(&s);
//初始化栈之后,判断栈是否为空
printf("初始化栈之后,判断栈是否为空:%d\n", StackEmpty(&s));
//入栈
Push(&s, 1);
Push(&s, 2);
Push(&s, 3);
Push(&s, 4);
//遍历栈
printf("入栈之后,遍历栈:\n");
StackTraverse(&s);
//入栈之后,判断栈是否为空
printf("入栈之后,判断栈是否为空:%d\n", StackEmpty(&s));
//出栈
int val;
Pop(&s, &val);
printf("出栈之后,遍历栈:\n");
StackTraverse(&s);
printf("出栈元素值为:%d\n", val);
//求栈的长度
printf("栈长:%d\n", StackLength(&s));
//清栈
ClearStack(&s);
printf("清栈之后,判断栈是否为空:%d\n", StackEmpty(&s));
return 0;
}
三、两栈共享空间
初始化:top=-1,top2=MAXSIZE;
//两栈共享空间,top1为栈1栈顶指针,初始化为-1;top2为栈2栈顶指针,初始化为MAXSIZE
#include<stdio.h>
typedef int bool;
#define true 1
#define false 0
#define MAXSIZE 100
typedef struct
{
int data[MAXSIZE];
int top1, top2;
}SqDoubleStack;
//初始化栈,top1=-1,top2=MAXSIZE
void InitStack(SqDoubleStack *s)
{
s->top1 = -1;
s->top2 = MAXSIZE;
}
//判断栈是否为空,是返回true,不是返回false,栈为空时top1==-1并且top2==MAXSIZE
bool StackEmpty(SqDoubleStack *s)
{
if (s->top1 == -1 && s->top2 == MAXSIZE)
return true;
else
return false;
}
//栈满
bool StackFull(SqDoubleStack *s)
{
return s->top1 + 1 == s->top2;
}
//求栈的长度
int StackLength(SqDoubleStack *s)
{
return s->top1 + 1 + MAXSIZE - s->top2;
}
//入栈,flag表示入栈1还是栈2
bool Push(SqDoubleStack *s, int flag, int key)
{
//判断栈满
if (s->top1 + 1 == s->top2)
return false;
if (flag == 1)
{
s->data[++s->top1] = key;
return true;
}
else if (flag == 2)
{
s->data[--s->top2] = key;
return true;
}
return false;//flag等于其他数
}
//出栈
bool Pop(SqDoubleStack *s, int flag, int *key)
{
//栈1出栈
if (flag == 1)
{
if (s->top1 == -1)
return false;
*key = s->data[s->top1--];
return true;
}
else if (flag == 2)
{
if (s->top2 == MAXSIZE)
return false;
*key = s->data[s->top2++];
return true;
}
return false;
}
//遍历栈
void StackTraverse(SqDoubleStack *s)
{
for (int i = 0; i <= s->top1; i++)
printf("%d ", s->data[i]);
for (int j = s->top2; j <= MAXSIZE - 1; j++)
printf("%d ", s->data[j]);
printf("\n");
}
int main(void)
{
SqDoubleStack s;
InitStack(&s);
printf("初始化栈后,栈是否为空:%d\n", StackEmpty(&s));
printf("给栈1入几个元素\n");
Push(&s, 1, 10);
Push(&s, 1, 20);
Push(&s, 1, 30);
printf("给栈2入几个元素:\n");
Push(&s, 2, 100);
Push(&s, 2, 200);
Push(&s, 2, 300);
printf("遍历栈:\n");
StackTraverse(&s);
printf("栈长度为:%d\n", StackLength(&s));
printf("栈1出栈\n");
int key;
Pop(&s, 1, &key);
printf("出栈元素为:%d\n", key);
printf("栈2出栈\n");
Pop(&s, 2, &key);
printf("出栈元素为:%d\n", key);
printf("遍历栈:\n");
StackTraverse(&s);
return 0;
}