1.栈的原理
栈是限制在一端进行插入操作和删除操作的线性表(俗称堆栈),允许进行操作的一端称为“栈顶”,另一固定端称为“栈底”,当栈中没有元素时称为“空栈”。特点 :后进先出(LIFO)。
2.顺序栈
它是顺序表的一种,具有顺序表同样的存储结构,由数组定义,配合用数组下标表示的栈顶指针top(相对指针)完成各种操作。
typedef int data_t ; /*定义栈中数据元素的数据类型*/
typedef struct
{
data_t *data ; /*用指针指向栈的存储空间*/
int maxlen; /*当前栈的最大元素个数*/
int top ; /*指示栈顶位置(数组下标)的变量*/
} sqstack; /*顺序栈类型定义*/
创建栈与释放栈
// 一个栈可以分为两处内存空间,一处是存放栈信息的结构体内存空间,一处是存放栈元素的内存空间
sqstack * stack_create(int len) {
sqstack * s;
// 一个结构体内存空间,结构体成员描述了栈的信息,其中data指针指向一段内存空间,用来存放栈的元素
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;
}
int stack_free(sqstack *s) {
if (s == NULL) {
printf("s is NULL\n");
return -1;
}
if (s->data != NULL)
free(s->data); // 先释放s中的data,再释放s
free(s);
return 0;
}
入栈与出栈
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从0开始索引
printf("stack is full\n");
return -1;
}
s->top++;
s->data[s->top] = value; // top代表栈顶元素的位置
return 0;
}
data_t stack_pop(sqstack *s) { // 出栈
s->top--;
return (s->data[s->top+1]); // 返回出栈元素,这里的top+1不会让top真的+1,只是临时的
}
空栈与满栈
/*
*@ret 1-empty
* */
int stack_empty(sqstack *s) {
if (s == NULL) {
printf("s is NULL\n");
return -1;
}
return (s->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_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;
}
3.链式栈
插入操作和删除操作均在链表头部进行,链表尾部就是栈底,栈顶指针就是头指针。
typedef int data_t;
typedef struct node {
data_t data;
struct node *next;
}listnode, *linkstack;
创建栈与释放栈
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;
}
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;
}
入栈与出栈
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;
}
data_t stack_pop(linkstack s) {
linkstack p; // p用来释放
data_t t;
p = s->next;
s->next = p->next;
t = p->data; // t用来存储返回值
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);
}