一、栈-顺序栈的原理
栈是限制在一端进行插入操作和删除操作的线性表(俗称堆栈)。
允许进行操作的一端称为“栈顶”。
另一固定端称为“栈底”。
当栈中没有元素时称为“空栈”。
特点 :后进先出(LIFO)。
二、栈-顺序栈的实现
1.定义
顺序栈是顺序表的一种,具有顺序表同样的存储结构,由数组定义,配合用数组下标表示的栈顶指针top(相对指针)完成各种操作。
typedef int data_t; /*定义栈中数据元素的数据类型*/
typedef struct
{
data_t *data; /*用指针指向栈的存储空间*/
int maxlen; /*当前栈的最大元素个数*/
int top; /*指示栈顶位置(数组下标)的变量*/
}sqstack; /*顺序栈类型定义*/
2.常用命令
1)创建栈
sqstack * stack_create(int len) {
sqstack * s;
if ((s =(sqstack *)malloc(sizeof(sqstack))) == NULL) {
printf("malloc sqstack failed\n");
return NULL;
}
if ((s->data = (data_t *)malloc(len * sizeof(data_t)))==NULL) {
printf("malloc data failed\n");
free(s);
return NULL;
}
memset(s->data, 0, len*sizeof(data_t));
s->maxlen = len;
s->top = -1;
return s;
2)清空栈
stack_clear(sqstack *s)
{
if (s == NULL) {
printf("s is NULL\n");
return -1;
}
s->top = -1 ;
}
3)判断栈是否空
int stack_empty(sqstack *s) {
if (s == NULL) {
printf("s is NULL\n");
return -1;
}
return (s->top == -1 ? 1 : 0);
}
4)判断栈是否满
int stack_full(sqstack *s) {
if (s == NULL) {
printf("s is NULL\n");
return -1;
}
return (s->top == s->maxlen-1 ? 1 : 0);
}
5)进栈
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;
}
6)出栈
data_t stack_pop(sqstack *s)
{
s->top--;
return (s->data[s->top+1]);
}
7)取栈顶元素
datatype get_top(sqstack *s)
{
return (s->data[s->top]);
}
8)清空
int stack_clear(sqstack *s) {
if (s == NULL) {
printf("s is NULL\n");
return -1;
}
s->top = -1;
return 0;
}
9)释放
int stack_free(sqstack *s) {
if (s == NULL) {
printf("s is NULL\n");
return -1;
}
if (s->data != NULL)
free(s->data);
free(s);
return 0;
}
3.实现
头文件 sqstack.h
typedef int data_t;
typedef struct {
data_t *data;
int maxlen;
int top;
}sqstack;
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);//出栈
data_t stack_top(sqstack *s);//取栈顶元素
int stack_clear(sqstack *s);//栈清空
int stack_free(sqstack *s);//栈销毁
源程序 sqstack.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sqstack.h"
sqstack * stack_create(int len) {
sqstack * s;//声明
if ((s =(sqstack *)malloc(sizeof(sqstack))) == NULL) {//栈的空间
printf("malloc sqstack failed\n");
return NULL;
}
if ((s->data = (data_t *)malloc(len * sizeof(data_t)))==NULL) {//栈中data的空间
printf("malloc data failed\n");
free(s);//栈空间申请成功而元素空间未申请成功,也要释放栈空间
return NULL;
}
memset(s->data, 0, len*sizeof(data_t));//所有元素赋初值0
s->maxlen = len;//栈长度为len
s->top = -1;//top为-1 //最开始栈里没有元素,top位于栈底,随着元素的入栈,top上移
return s;
}
//入栈
int stack_push(sqstack * s, data_t value) {
if (s == NULL) {
printf("s is NULL\n");
return -1;
}
if (s->top == s->maxlen-1) {//top到达栈顶maxlen-1,则栈满
printf("stack is full\n");
return -1;
}
s->top++;//top先增加
s->data[s->top] = value;//再入栈
return 0;
}
/*
*@ret 1-empty
* */
int stack_empty(sqstack *s) {
if (s == NULL) {
printf("s is NULL\n");
return -1;
}
return (s->top == -1 ? 1 : 0);//top=-1则返回1,为空;返回0,为满
}
/*
* @ret 1-full
* */
int stack_full(sqstack *s) {
if (s == NULL) {
printf("s is NULL\n");
return -1;
}
return (s->top == s->maxlen-1 ? 1 : 0);
}
//出栈
data_t stack_pop(sqstack *s) {
s->top--;//top下移
return (s->data[s->top+1]);//出栈的值还在缓存空间,可以使用
}
data_t stack_top(sqstack *s) {
return (s->data[s->top]);
}
int stack_clear(sqstack *s) {//清空栈,并非释放内存
if (s == NULL) {
printf("s is NULL\n");
return -1;
}
s->top = -1;
return 0;
}
int stack_free(sqstack *s) {//释放内存,即销毁栈
if (s == NULL) {
printf("s is NULL\n");
return -1;
}
if (s->data != NULL)
free(s->data);//先释放内层元素
free(s);//再释放外层栈
return 0;
}
测试文件 test.c
#include <stdio.h>
#include "sqstack.h"
int main(int argc, const char *argv[])
{
sqstack *s;
s = stack_create(100);
if (s == NULL)
return -1;
stack_push(s, 10);
stack_push(s, 20);
stack_push(s, 30);
stack_push(s, 40);
while (!stack_empty(s)) {//先判断是否为空,再出栈
printf("pop: %d \n", stack_pop(s) );
}
stack_free(s);
return 0;
}
三、栈-链式栈的原理
1.定义
插入操作和删除操作均在链表头部进行,链表尾部就是栈底,栈顶指针就是头指针。
typedef int data_t; /*定义栈中数据元素数据类型*/
typedef struct node_t{
data_t data; /*数据域*/
struct node_t *next; /*链接指针域*/
} linkstack_t; /*链栈类型定义*/
四、栈-链式栈的实现
1.常用命令
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)判断是否空栈
int stack_empty(linkstack s) {
if (s == NULL) {
printf("s is NULL\n");
return -1;
}
return (s->next == NULL ? 1 : 0);
}
3)入栈
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));//申请p节点空间
if (p == NULL) {
printf("malloc failed\n");
return -1;
}
p->data = value;//初始化
//p->next = NULL;
p->next = s->next;//p从栈顶(头节点之后)插入
s->next = p;
return 0;
}
4)出栈
data_t stack_pop(linkstack s) {
linkstack p;
data_t t;
p = s->next;//头节点之后的元素出栈
s->next = p->next;
t = p->data;
free(p);
p =NULL;
return t;
}
5)栈顶元素
data_t stack_top(linkstack s) {
return (s->next->data);
}
6)释放
linkstack stack_free(linkstack s) {
linkstack p;
if (s == NULL) {
printf("s is NULL\n");
return NULL;
}
while (s != NULL) {
p = s;//头结点也需要释放
s = s->next;
printf("free:%d\n", p->data);
free(p);
}
return NULL;
}
2.实现
头文件 linkstack.h
typedef int data_t;
typedef struct node {
data_t data;
struct node *next;
}listnode, *linkstack;
linkstack stack_create();
int stack_push(linkstack s, data_t value);
data_t stack_pop(linkstack s);
int stack_empty(linkstack s);
data_t stack_top(linkstack s);
linkstack stack_free(linkstack s);
源程序 linkstack.c
#include <stdio.h>
#include <stdlib.h>
#include "linkstack.h"
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; //栈底->next为空
return s;
}
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 = NULL; //孤立节点p
p->next = s->next; //先连后继
s->next = p; //再连前驱
return 0;
}
data_t stack_pop(linkstack s) {
linkstack p;
data_t t;
p = s->next; //p先指向要删除的目标
s->next = p->next; //跨越节点p
t = p->data; //临时变量保存要删除的目标
free(p); //释放
p =NULL;
return t; //返回要删除的目标
}
int stack_empty(linkstack s) {
if (s == NULL) {
printf("s is NULL\n");
return -1;
}
return (s->next == NULL ? 1 : 0); //返回1则为空
}
data_t stack_top(linkstack s) {
return (s->next->data);
}
linkstack stack_free(linkstack s) {
linkstack p;
if (s == NULL) {
printf("s is NULL\n");
return NULL;
}
while (s != NULL) {
p = s; //先释放头结点
s = s->next; //栈顶先后移再释放p
printf("free:%d\n", p->data);
free(p);
}
return NULL;
}
测试文件 test.c
#include <stdio.h>
#include <stdlib.h>
#include "linkstack.h"
int main(int argc, const char *argv[])
{
linkstack s;
s = stack_create();
if (s == NULL)
return -1;
stack_push(s, 10);
stack_push(s, 20);
stack_push(s, 30);
stack_push(s, 40);
#if 0
while (!stack_empty(s)) {
printf("pop:%d\n", stack_pop(s));
}
#endif
s = stack_free(s);
return 0;
}
五、作业
1、一个栈的入栈序列是abcde,则栈的不可能的输出序列是(C) ?
A edcba B decba C dceab D abcde
2、请简述栈和线性表有什么关系;
栈是特殊的线性表,是只允许在一端进行插入和删除的线性表。
3、分别写出顺序栈和链式栈实现时用的结构体;
顺序表
typedef int data_t;
typedef struct
{
data_t *data;
int maxlen;
int top;
}sqstack;
链式表
typedef int data_t;
typedef struct node_t{
data_t data;
struct node_t *next;
}linkstack_t;