一、栈
1.概念:
栈是限制在一段进行插入操作和删除操作的线性表(俗称堆栈)
允许进行操作的一段称为“栈顶”,另一端为“栈底”
当栈中没有元素时,称为空栈。栈的特点是后进先出(last in first out),先进后出。
栈分为顺序栈和链式栈
顺序栈
顺序栈也是顺序表的一种,具有顺序表同样的存储结构,由数组定义,配合用数组下标表示栈顶指针top完成各种操作
顺序栈的定义代码如下:当然结构体成员里面的数组也可以定义为data[N]
typedef int data_t;
typedef struct
{
data_t *data;//数组,这也是要申请内存的
int maxlen;//长度
int top;//栈顶的下标,也是记录最大数组的下标,注意和maxlen的区别
}sqstack; //sqtack是结构体类型
栈的部分操作如下:
sqstack* stack_create(int len);//创建一个栈
int stack_push(sqstack *s, data_t value);//某个值要入栈
int stack_empty(sqstack *s);
int stack_full(sqstack *s);
data_t stack_pop(sqstack *s);//出栈,s是栈顶
data_t stack_top(sqstack *s);//栈顶元素是多少
int stack_clear(sqstack *s);
int stack_free(sqstack *s);
2.各个函数具体实现如下:
2.1 栈的创建
如下图:
首先就是定义一个结构体类型的指针变量,然后为其申请空间,为其里面的data申请空间,最后初始化就行了,初始化可以用memset函数,注意,申请空间时,如果data的空间申请失败,则整个空间的申请就是失败的,失败时需要释放整个申请的空间
具体代码如下:
sqstack * stack_create(int len)//创建一个栈
{
sqstack *s;//s是一个结构体类型的指针变量
if ((s = (sqstack *)malloc(sizeof(sqstack))) == NULL)//第一次申请s的空间
{
printf("malloc sqstack failed\n");
return NULL;
}
if ((s->data = (data_t *)malloc(len *sizeof(data_t))) == NULL)//申请的s->data的空间
{
printf("malloc data falied\n");
free(s);
return NULL;
}
memset(s->data,0,len*sizeof(data_t));//s->data初始化,s->data是起始地址
s->maxlen = len;//栈的最大元素容量len是用户提供
s->top = -1;//
return s;
}
2.2 是否满栈
核心就是判断s->top是否等于s->maxlen-1
具体代码如下:约定返回1就是满栈
int stack_full(sqstack *s)//是否满栈
{
if (s == NULL)
{
printf("s is NULL\n");
return -1;
}
return (s->top == s->maxlen-1 ? 1 : 0);
}
2.3 是否空栈
主要判断s->top是否为-1,top是下标,约定下标为-1时代表空栈
int stack_empty(sqstack *s)//判断是否为空栈
{
if (s == NULL)
{
printf("s is NULL\n");
return -1;
}
return (s->top == -1 ? 1 : 0);
}
2.4 某个值要入栈
首先 要判断栈是否为空,或者满了
然后栈顶的top++;s->data[s->top]=value
具体代码如下:
int stack_push(sqstack *s, data_t value)//某个值要入栈
{
if (s == NULL)//判断是否为空
{
printf("s is NULL\n");
return -1;
}
if (s->top == s->maxlen - 1)//判断栈是否满了
{
printf("stack is full\n");
return -1;
}
s->top++;
s->data[s->top] = value;
return 0;
}
2.4 某个值要出栈
出栈是从栈顶开始出栈,栈顶的元素的s->data[s->top+1]
具体代码如下:
data_t stack_pop(sqstack *s)//出栈,s是栈顶
{
s->top--;
return (s->data[s->top + 1]);//要出栈的值
}
2.5 清空栈内的元素
只需调整top就行,top=-1就代表栈是空的了
具体代码如下:
data_t stack_clear(sqstack *s)//清空栈内元素
{
if (s == NULL)
{
printf("s is NULL\n");
return -1;
}
s->top=-1;
return 0;
}
2.6 栈空间的释放
栈的释放时,先释放内层,在释放外层,具体操作时有两种方式,当外层申请成功,内层失败时,只需释放外层就可以(free(s))
也可以写个函数进行释放先free[s->data],后free(s),具体函数代码如下:
int stack_free(sqstack *s)
{
if (s == NULL)
{
printf("s is NULL\n");
return -1;
}
if (s->data != NULL)//栈申请成功,s->data失败时
{
free(s->data);
free(s);
}
return 0;
}
二、链式栈(和链表有关)
链式栈的插入和删除操作均在链表的头部进行,链表的尾部就是栈底,栈顶指针就是头指针
链式栈的结构体类型定义
typedef int data_t;
typedef struct node
{
data_t data;
struct node *next;//结构体类型的指针
}listnode,*linkstack;
2.1链式栈的创建
具体代码如下:
linkstack stack_create()
{
linkstack s;
s = (linkstack)malloc(sizeof(listnode));
if (s = NULL)
{
printf("malloc failed\n");
return NULL;
}
s->data = 0;
s ->next = NULL;
return s;
}
2.2 入栈操作
具体代码如下:
int stack_push(linkstack s, data_t value)//入栈
{
linkstack p;
if (s == NULL)
{
printf("s is NULL\n");
return -1;
}
p= (linkstack)malloc(sizeof(listnode));
if (p = NULL)
{
printf("malloc failed\n");
return -1;
}
//注意等号左右两边
p->data = value;
p->next = s->next;
s->next = p;
return 0;
}
2.3 出栈操作
1.先找个指针p存储待出栈的元素s->next
2.修改s的指向,指向待出栈元素的下一个节点
3.释放出栈元素所占的空间(释放之前先保存)
具体代码实现:
data_t stack_pop(linkstack s)//出栈
{
linkstack p;
data_t t;
p = s->next;
s->next = p->next;
t = p->next;
free(p);
p = NULL;
return t;
}