概念
关于栈的相关内容,在之前的文章已经详细介绍过了,请参见《也没想象中那么神秘的数据结构-后来居上的“栈”》,本文主要将链栈相关内容。
链式栈:采用链式储存结构的栈,使用单链表来实现。将单链表的第一个结点为栈顶结点,栈总是指向栈顶结点。
核心
栈的结构:栈总是指向栈顶节点,栈底节点指向NULL,节点与节点之间通过指针一环扣一环连接起来。
入栈:在栈顶节点之前插入新节点操作,插入的时候注意节点指针指向的改变。
出栈:删除当前栈顶节点,并将之前栈顶节点指向的下一个节点作为栈顶节点的操作,弹出的时候注意节点指针指向的改变。
示例
★包含头文件stack_list.h和源文件stack_list.c(均已验证通过)。
stack_list.h
/** * @Filename : stack_list.h * @Revision : $Revision: 1.0 $ * @Author : Feng(微信公众号:不只会拍照的程序猿) * @Description : 链栈示例 **/ #ifndef __STACK_LIST_H__ #define __STACK_LIST_H__ #include <stdio.h> #include <stdlib.h> #define MAX_SIZE 10 /* 栈最大元素个数 */ /* 栈节点元素定义 */ struct t_node{ int data; /* 元素值 */ struct t_node *p_next; /* 指向下一个元素 */ }; /* 栈空间定义 */ struct t_stack{ struct t_node *p_top; /* 栈顶元素 */ int size; /* 元素个数 */ }; /** * @初始化栈 * @p_stack:栈 **/ void stack_init(struct t_stack *p_stack); /** * @清除栈 * @p_stack:栈 **/ void stack_deinit(struct t_stack *p_stack); /** * @判断栈是否已满 * @p_stack:栈 * @返回1表示已满,0表示未满 **/ int stack_is_full(const struct t_stack *p_stack); /** * @判断栈是否已空 * @p_stack:栈 * @返回1表示已空,0表示未空 **/ int stack_is_empty(const struct t_stack *p_stack); /** * @获取栈元素个数 * @p_stack:栈 * @返回元素个数 **/ int stack_get_size(const struct t_stack *p_stack); /** * @入栈操作 * @p_stack:栈 data:待插入元素 * @返回1表示成功,0表示失败 **/ int stack_push(struct t_stack *p_stack, int data); /** * @出栈操作 * @p_stack:栈 p_data:保存出栈元素 * @返回1表示成功,0表示失败 **/ int stack_pop(struct t_stack *p_stack, int *p_data); /** * @获取栈顶元素 * @p_stack:栈 p_data:保存栈顶元素 * @返回1表示成功,0表示失败 **/ int stack_get_top(const struct t_stack *p_stack, int *p_data); /** * @打印栈元素内容 * @p_stack:栈 **/ void stack_print(const struct t_stack *p_stack); #endif
stack_list.c
/** * @Filename : stack_list.c * @Revision : $Revision: 1.0 $ * @Author : Feng(微信公众号:不只会拍照的程序猿) * @Description : 链栈示例 **/ #include "stack_list.h" /** * @初始化栈 * @p_stack:栈 **/ void stack_init(struct t_stack *p_stack) { p_stack->size = 0; p_stack->p_top = NULL; } /** * @清除栈 * @p_stack:栈 **/ void stack_deinit(struct t_stack *p_stack) { struct t_node *p_tmp = NULL, *p_node = p_stack->p_top; while(p_node) { p_tmp = p_node; p_node = p_node->p_next; free(p_tmp); } p_stack->size = 0; } /** * @判断栈是否已满 * @p_stack:栈 * @返回1表示已满,0表示未满 **/ int stack_is_full(const struct t_stack *p_stack) { return (p_stack->size >= MAX_SIZE); } /** * @判断栈是否已空 * @p_stack:栈 * @返回1表示已空,0表示未空 **/ int stack_is_empty(const struct t_stack *p_stack) { return (p_stack->size == 0); } /** * @获取栈元素个数 * @p_stack:栈 * @返回元素个数 **/ int stack_get_size(const struct t_stack *p_stack) { return (p_stack->size); } /** * @创建节点 * @data:元素值 * @返回节点地址,NULL表示失败 **/ static struct t_node *creat_node(int data) { struct t_node *p_node = (struct t_node *)malloc(sizeof(struct t_node)); if (p_node == NULL) return NULL; p_node->data = data; p_node->p_next = NULL; return p_node; } /** * @入栈操作 * @p_stack:栈 data:待插入元素 * @返回1表示成功,0表示失败 **/ int stack_push(struct t_stack *p_stack, int data) { struct t_node *p_node = NULL; if (p_stack->size >= MAX_SIZE) return 0; if ((p_node = creat_node(data)) == NULL) return 0; p_node->p_next = p_stack->p_top; p_stack->p_top = p_node; p_stack->size++; return 1; } /** * @出栈操作 * @p_stack:栈 p_data:保存出栈元素 * @返回1表示成功,0表示失败 **/ int stack_pop(struct t_stack *p_stack, int *p_data) { struct t_node *p_node = NULL; if (p_stack->size == 0) return 0; p_node = p_stack->p_top; p_stack->p_top = p_stack->p_top->p_next; *p_data = p_node->data; free(p_node); p_stack->size--; return 1; } /** * @获取栈顶元素 * @p_stack:栈 p_data:保存栈顶元素 * @返回1表示成功,0表示失败 **/ int stack_get_top(const struct t_stack *p_stack, int *p_data) { if (p_stack->size == 0) return 0; *p_data = p_stack->p_top->data; return 1; } /** * @打印栈元素内容 * @p_stack:栈 **/ void stack_print(const struct t_stack *p_stack) { struct t_node *p_node = p_stack->p_top; while(p_node) { printf("%d ", p_node->data); p_node = p_node->p_next; } printf("\n"); } /** * @链栈测试代码 **/ int main(void) { int data; struct t_stack my_stack; stack_init(&my_stack); /* 初始化栈,此时为空栈 */ printf("the stack is %s\n", stack_is_empty(&my_stack) ? "empty" : "not empty"); printf("---------------------------------------\n"); /* 压栈,栈:25 41 16 7 8 19 22,元素个数为7 */ stack_push(&my_stack, 25); stack_push(&my_stack, 41); stack_push(&my_stack, 16); stack_push(&my_stack, 7); stack_push(&my_stack, 8); stack_push(&my_stack, 19); stack_push(&my_stack, 22); printf("the size of stack is: %d\n", stack_get_size(&my_stack)); stack_print(&my_stack); printf("---------------------------------------\n"); /* 压栈35 38 11 22(栈已满,入栈失败),栈:25 41 16 7 8 19 22 35 38 11,个数10 */ stack_push(&my_stack, 35); stack_push(&my_stack, 38); stack_push(&my_stack, 11); stack_push(&my_stack, 22); printf("the size of stack is: %d\n", stack_get_size(&my_stack)); stack_print(&my_stack); printf("the stack is %s\n", stack_is_full(&my_stack) ? "full" : "not full"); printf("---------------------------------------\n"); /* 栈顶元素为11,第一次出栈11,第二次出栈38,栈:25 41 16 7 8 19 22 35,个数8 */ if (stack_get_top(&my_stack, &data)) printf("the top stack data is: %d\n", data); if (stack_pop(&my_stack, &data)) printf("the pop stack data is: %d\n", data); if (stack_pop(&my_stack, &data)) printf("the pop stack data is: %d\n", data); printf("the size of stack is: %d\n", stack_get_size(&my_stack)); stack_print(&my_stack); printf("---------------------------------------\n"); /* 清除栈,个数0 */ stack_deinit(&my_stack); printf("the size of stack is: %d\n", stack_get_size(&my_stack)); return 0; }
结论
feng:stack$ gcc -o stack_list stack_list.c feng:stack$ ./stack_list the stack is empty --------------------------------------- the size of stack is: 7 22 19 8 7 16 41 25 --------------------------------------- the size of stack is: 10 11 38 35 22 19 8 7 16 41 25 the stack is full --------------------------------------- the top stack data is: 11 the pop stack data is: 11 the pop stack data is: 38 the size of stack is: 8 35 22 19 8 7 16 41 25 --------------------------------------- the size of stack is: 0 feng:stack$
本示例仅为链栈示例,公众号也提供顺序栈示例《也没想象中那么神秘的数据结构-后来居上的“栈”》,以及栈的典型应用示例。
关注
更多精彩内容,请关注微信公众号:不只会拍照的程序猿,本人致力分享linux、设计模式、C语言、嵌入式、编程相关知识,也会抽空分享些摄影相关内容,同样也分享大量摄影、编程相关视频和源码,另外你若想要本文章源码请关注公众号:不只会拍照的程序猿,后台回复:数据结构源码,也可点击此处下载。