1. 栈(stack)
1. 栈:只允许在一端进行插入、删除的线性数据结构。允许插入和删除的一端叫做栈顶, 另一端叫做栈底。
2. 栈分为顺序栈和链式栈,本文主要介绍顺序栈的使用,想了解链式栈的朋友欢迎浏览下期内容!
3. 栈的特点: 先进后出。顺序栈占用一片连续存储空间进行操作,链式栈则是分散存储。
4. 我们依旧准备三个文件:stack.c、stack.h、main.c。
5. 请大家多看注释可帮助理解运用!
2. 创建栈
栈的功能函数中不仅有 “ 出栈入栈 ” 还有一系列辅助实现功能的函数——判空、判满、清空、回收、求有效数据长度、显示栈元素函数。
(1)stack.h
在头文件中,定义栈的大小SIZE、定义栈结构体、做函数声明等操作。
#ifndef _stack_h_
#define _stack_h
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//宏定义栈(数组)大小
#define SIZE 10
//重命名数据类型int
typedef int data_t;
//顺序栈结构体
typedef struct stack{
data_t data[SIZE]; //顺序栈用数组做栈体
int top; //栈顶指针:用来操作插入、删除(实质非指针)
}stack;
//创建顺序栈
stack *stack_create();
//判空
int stack_empty(stack *head); //head是手动开辟空间的首地址
//判满
int stack_full(stack *head);
//清空栈
void stack_clear(stack *head);
//回收栈
void stack_destroy(stack **head);
//获取栈的长度
int stack_length(stack *head);
//显示栈的数据
void stack_display(stack *head);
#endif
(2)stack.c
封装判空、判满、清空、回收、求有效数据长度、显示栈元素函数的功能。
#include "stack.h"
//创建顺序栈
stack *stack_create()
{
//给栈结构体开辟空间
stack *head = (stack *)malloc(sizeof(stack));
if (NULL == head)
{
printf("malloc failed!");
return NULL;
}
//给给开辟的空间填充0
memset(head, 0, sizeof(stack));
head->top = -1; //栈顶指针初始化为-1表示没有元素
//返回空间入口地址
return head;
}
//判空
int stack_empty(stack *head)
{
if (-1 == head->top)
{
printf("Stack is empty!\n");
return 1;
}
return 0;
}
//判满
int stack_full(stack *head)
{
if (SIZE - 1 == head->top)
return 1;
return 0;
}
//清空栈
void stack_clear(stack *head)
{
head->top = -1;
}
//回收栈
void stack_destroy(stack **head)
{
free(*head);
*head = NULL;
}
//获取栈的长度
int stack_length(stack *head)
{
return (head->top + 1);
}
//遍历栈的数据
void stack_display(stack *head)
{
for(int i = 0; i < head->top+1; i++)
printf("%-3d", head->data[i]);
puts("");
}
3. 出入栈以及获取栈顶元素
(1)stack.h
在头文件中加入函数声明。
//入栈
int stack_push(stack *head, data_t data);
//出栈
data_t stack_pop(stack *head);
//获取栈顶元素
data_t stack_top(stack *head);
有同学可能会疑问:出栈和获取栈顶元素感觉是差不多的意思呢?
其实获取栈顶元素只是将当前栈顶的数据返回,可供用户打印,而出栈操作不仅包含了获取栈顶元素的功能,额外还将栈顶元素删除,使栈的有效元素减一。
所以在只是想知道栈顶元素的情况下,可使用获取栈顶元素函数;在不仅想知道栈顶元素,还想删除栈顶元素时,使用出栈函数。
(2)stack.c
封装出入栈以及获取栈顶函数的功能。
//入栈
int stack_push(stack *head, data_t data)
{
//判满
if (stack_full(head))
{
printf("Stack is full! Push failed!\n");
return -1;
}
//有效元素+1
head->top += 1;
//插入数据
head->data[head->top] = data;
return 0;
}
//出栈
data_t stack_pop(stack *head)
{
//判空
if (stack_empty(head))
{
printf("Stack is empty! Pop failed!\n");
return -1;
}
//记录栈顶元素
data_t data = head->data[head->top];
//有效元素-1
head->top -= 1;
//返回已删除的栈顶数据
return data;
}
//获取栈顶元素
data_t stack_top(stack *head)
{
//判空
if (stack_empty(head))
{
printf("Stack is empty! Pop failed!\n");
return -1;
}
//返回栈顶元素
return head->data[head->top];
}
4. 在主函数中验证栈的功能
(1)main.c
#include "stack.h"
int main(int argc, char *argv[])
{
//创建顺序栈
stack *head = stack_create();
if (NULL == head)
{
printf("malloc failed!\n");
return -1;
}
//插入十个数(入栈)
printf("插入十个数:\n");
int i = 0;
while(i++ < 10)
stack_push(head, i);
//展示插入数据后的栈
stack_display(head);
//出栈
printf("出栈操作.出栈的元素为:%d\n", stack_pop(head));
stack_display(head);
//获取栈顶元素
printf("栈顶元素为:%d\n", stack_top(head));
//回收顺序栈
stack_destroy(&head); //参数是二级指针,所以需要传入一级指针的地址
return 0;
}
注:有些同学很爱忽略回收栈这一步,但记得malloc手动开辟的空间一定要及时free,否则会造成内存泄漏。
(2)运行结果展示
插入十个数:
1 2 3 4 5 6 7 8 9 10
出栈操作.出栈的元素为:10
1 2 3 4 5 6 7 8 9
栈顶元素为:9
5. 总结
1. 栈的先进后出是它独有的特点,可运用在实现递归、表达式求值等方面。
2. 栈也是线性数据结构的一种,另外线性数据结构还包括线性表(顺序表、链表)、队列,它们各有各的特色,如想了解其他线性结构的使用,欢迎浏览主页相关文章!
3. 除了顺序栈,链式栈也有着他独有的特点,那链式栈怎样实现呢?
敬请期待下集:C语言链式栈的实现(linkstack)
感谢观看!如有疑问欢迎提出!
----香菜小猫祝这位uu天天开心----