一、定义
栈是限制在一端进行插入操作和删除操作的线性表 ,
允许进行操作的一端称为“栈顶”, 另一固定端称为“栈底”,
当栈中没有元素时称为“空栈”。
逻辑结构:线性结构
存储结构:顺序存储、链式存储
特点:先进后出(FILO)
二、顺序栈
将栈采用顺序存储,它是顺序表的一种, 具有顺序表同样的存储结构, 由数组定义, 配合用数组下标表示的栈顶指针top( 相对指针)
完成各种操作。
其结构体定义如下:
typedef int data_t;
typedef struct seqstack
{
data_t buf[N];//数据
int top;//栈顶指针
}
顺序栈的基本操作函数如下:
/*===============================================
* 文件名称:stack.c
* 创 建 者:xm
* 创建日期:2022年07月30日
* 描 述:
================================================*/
#include "stack.h"
//创建栈
Seqstack *create_seqstack()
{
Seqstack *s =(Seqstack *)malloc(sizeof(Seqstack));
if(NULL==s)
{
printf("malloc falied\n");
return NULL;
}
memset(s->buf,0,sizeof(data_t)*N);
s->top=-1;
return s;
}
//判断是否为空栈
int seqtack_is_full(Seqstack *s)
{
if(s->top==N-1)return 1;
else return 0;
}
//栈是否已满
int seqtack_is_empty(Seqstack *s)
{
if(s->top==-1)return 1;
else return 0;
}
//压栈
void seqstack_push(Seqstack *s,data_t data)
{
if(seqtack_is_full(s)==1)
{
printf("full!\n");
return;
}
s->top++;
s->buf[s->top]=data;
}
//弹栈
void seqstack_pop(Seqstack *s,data_t *data)
{
if(seqtack_is_empty(s)==1)
{
printf("full!\n");
return;
}
*data=s->buf[s->top];
s->top--;
}
//测试,将一个十进制数转为二进制输出
void seqstack_test(Seqstack *s,int num)
{
int bit;
while(num)
{
bit=num%2;
seqstack_push(s,bit);
num=num/2;
}
while(s->top!=-1)
{
seqstack_pop(s,&bit);
printf("%d ",bit);
}
printf("\n");
}
头文件如下:
/*===============================================
* 文件名称:stack.h
* 创 建 者:xm
* 创建日期:2022年07月30日
* 描 述:
================================================*/
#ifndef _STACK_
#define _STACK_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 64
typedef int data_t;
typedef struct seqstack
{
data_t buf[N];
int top;//栈顶指针
}Seqstack;
Seqstack *create_seqstack();
int seqtack_is_full(Seqstack *s);
int seqtack_is_empty(Seqstack *s);
void seqstack_push(Seqstack *s,data_t data);
void seqstack_pop(Seqstack *s,data_t *data);
void seqstack_test(Seqstack *s,int num);
#endif
主函数测试:
#include "stack.h"
int main(int argc, char *argv[])
{
Seqstack *s=create_seqstack();
printf("输入一个整数\n");
scanf("%d",&data);
printf("转为二进制:\n");
seqstack_test(s,data);
return 0;
}
三、链栈
采用链式存储的栈称为链栈,链栈的优点是提高空间利用率,且不存在栈满上溢的情况。通常采用单链表实现,并规定所有操作都是在单链表的表头进行。
其结点结构体定义:
typedef struct linkstack
{
data_t data;//数据
struct linkstack *next;//指针域
}Linkstack;
相关操作函数:
/*===============================================
* 文件名称:linkstack.c
* 创 建 者:xm
* 创建日期:2022年07月30日
* 描 述:
================================================*/
#include "linkstack.h"
//创建栈
Linkstack *create_linkstack()
{
Linkstack *s=(Linkstack *)malloc(sizeof(Linkstack));
if(NULL==s)
{
printf("malloc error!\n");
return NULL;
}
s->data=-1;
s->next=NULL;
return s;
}
//判空
int linktack_is_empty(Linkstack *s)
{
if(s->next==NULL)return 1;
else return 0;
}
//压栈
void linkstack_push(Linkstack *s,data_t data)
{
Linkstack *p=(Linkstack *)malloc(sizeof(Linkstack));
if(NULL==p)
{
printf("malloc error!\n");
return;
}
p->data=data;
p->next=s->next;
s->next=p;
}
//出栈
void linkstack_pop(Linkstack *s,data_t *data)
{
if(linktack_is_empty(s)==1)
{
printf("stack is empty\n");
return ;
}
Linkstack *p=s->next;
*data=p->data;
s->next=p->next;
free(p);
p=NULL;
}
头文件:
/*===============================================
* 文件名称:linkstack.h
* 创 建 者:xm
* 创建日期:2022年07月30日
* 描 述:
================================================*/
#ifndef _LINKSTACK_
#define _LINKSTACK_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 64
typedef int data_t;
typedef struct linkstack
{
data_t data;//数据域
struct linkstack *next;//指针域
}Linkstack;
Linkstack *create_linkstack();
int linktack_is_empty(Linkstack *s);
void linkstack_push(Linkstack *s,data_t data);
void linkstack_pop(Linkstack *s,data_t *data);
int linkstack_work(Linkstack *s,int num);
#endif
主函数测试:
/*===============================================
* 文件名称:main.c
* 创 建 者:
* 创建日期:2022年07月30日
* 描 述:
================================================*/
#include "stack.h"
#include "linkstack.h"
int main(int argc, char *argv[])
{
Linkstack *s=create_linkstack();
int data=1,n=10;
while(n--)
{
linkstack_push(s,n);
}
while(s->next!=NULL)
{
linkstack_pop(s,&data);
printf("data=%d\n",data);
}
return 0;
}
总结:顺序栈与链栈在时间复杂度上相同,在空间性能上,顺序栈需要事先确定一个固定的长度,可能会存在内存空间浪费的问题,但它的优势是存取时定位很方便。而链栈则要求每个元素都有指针域,这同时也增加了一些内存开销,但对于栈的长度无限制。
所以如果栈的使用过程中元素变化不可预料,有时很小,有时非常大,那么最好是用链栈,反之,如果它的变化在可控范围内,建议使用顺序栈会更好一些。