数据结构 严薇敏 栈 的实现及其使用方法详解
目录
1.栈
1.1栈的概念及结构
1.2栈的实现
1.3接口以及实现
Stack.h
Stack.c
栈的初始化
入栈
出栈
获取栈顶元素
获取栈中有效元素的个数
检测栈是否为空
栈的销毁
扩容
测试
1.栈
1.1栈的概念及结构
栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。形象一点就是吃进去吐出来,只是在一端进行操作。
压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。
出栈:栈的删除操作叫做出栈。出数据也在栈顶。
1.2栈的实现
栈的话用动态顺序表实现就是比较简单的,当然也可用单链表实现,但是注意一个问题,栈是不可以被遍历的,我们就用顺序表来实现
顺序结构
链式结构
1.3接口以及实现
Stack.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
typedef int Datatype;//其实就是一个阉割版的顺序表
//我们知道栈是先进后出,只要给他的操作遵循就好了typedef struct Stack {//动态的栈Datatype* arr;int capacity;//标记栈顶int top;
}Stack;
//栈的初始化
void StackInit(Stack* p, int capacity);//入栈
void StackPush(Stack* p, Datatype data);//出栈
void StackPop(Stack* p);//获取栈顶元素
Datatype Stacktop(Stack* p);//获取栈的大小
int StackSize(Stack* p);//判断栈是否为空
int StackEmpty(Stack* p);//栈的销毁
void StackDestroy(Stack* p);//栈的扩容
//阉割版的顺序表呀在此就不再赘述
void StackCheckCapacity(Stack* p);
Stack.c
#include "Stack.h"
//栈的初始化
void StackInit(Stack* p, int capacity)
{//检测参数合法性assert(p);//对传入的capacity为负数的体现capacity = capacity <= 0 ? 3 : capacity;//动态在堆上申请空间来初始化栈p->arr = (Datatype* )malloc(sizeof(Stack) * capacity);//开辟未成功if (NULL == p->arr) {assert(0);}//更新参数p->capacity = capacity;p->top = 0;
}//入栈
void StackPush(Stack* p, Datatype data)
{StackCheckCapacity(p);//直接压栈把data放在栈顶指针这块p->arr[p->top] = data;//栈顶指针++p->top++;
}
//出栈
void StackPop(Stack* p)
{//先得看看是否为空if (StackEmpty(p)) {return;}//栈顶指针--p->top--;
}
//获取栈顶元素
Datatype Stacktop(Stack* p)
{//先得看看是否为空assert(p);if (StackEmpty(p)) {return;}// return ps->arr[--p->top]; // 错误写法return p->arr[p->top - 1];
}// 获取栈中有效元素的个数
int StackSize(Stack* p)
{//检测参数合法性assert(p);return p->top;
}// 检测栈是否为空,如果为空返回真,否则返回假
int StackEmpty(Stack* p)
{//检测参数合法性assert(p);return 0 == p->top;
}//栈的销毁
void StackDestroy(Stack* p)
{//检测参数合法性assert(p);//free掉防止内存泄露if (p->arr) {free(p->arr);p->capacity = 0;p->top = 0;}
}//扩容
//先申请新的内存空间
//把原来的数据拷贝到新扩容的空间里面去
//free掉原来空间,让arr指向新开辟的内存空间
void StackCheckCapacity(Stack* p)
{//检测参数合法性assert(p);if (p->capacity == p->top) {int Newcapacity = (p->capacity << 1);Datatype* temp = (Datatype*)malloc(sizeof(Datatype) * Newcapacity);if (NULL == temp) {assert(0);}memcpy(temp, p->arr, sizeof(Datatype) * p->capacity);free(p->arr);p->arr = temp;p->capacity = Newcapacity;}
}
int main() {Stack s;StackInit(&s,3);StackPush(&s, 1);StackPush(&s, 2);StackPush(&s, 3);printf("size = %d\n", StackSize(&s));printf("top = %d\n", Stacktop(&s));StackPush(&s, 4); // 扩容StackPush(&s, 5);StackPush(&s, 6);StackPush(&s, 7); // 扩容printf("size = %d\n", StackSize(&s));printf("top = %d\n", Stacktop(&s));StackPop(&s);StackPop(&s);StackPop(&s);printf("size = %d\n", StackSize(&s));printf("top = %d\n", Stacktop(&s));StackDestroy(&s);
}
栈的初始化
//栈的初始化
void StackInit(Stack* p, int capacity)
{//检测参数合法性assert(p);//对传入的capacity为负数的体现capacity = capacity <= 0 ? 3 : capacity;//动态在堆上申请空间来初始化栈p->arr = (Datatype* )malloc(sizeof(Stack) * capacity);//开辟未成功if (NULL == p->arr) {assert(0);}//更新参数p->capacity = capacity;p->top = 0;
}
- assret我们的老朋友先对参数合法性判断。
- 然后对capacity合法性判断,如果是负数就给他一个初始值,c++用缺省参数就规避掉了给他一个默认值就好了。
- 在堆上申请空间,然后对申请的空间进行判断是否申请成功了。
- 再更新我们的参数。
入栈
//入栈
void StackPush(Stack* p, Datatype data)
{StackCheckCapacity(p);//直接压栈把data放在栈顶指针这块p->arr[p->top] = data;//栈顶指针++p->top++;
}
- 压栈把data放在栈顶部位。
- 在把站栈顶指针向上移动。
出栈
//出栈
void StackPop(Stack* p)
{//先得看看是否为空if (StackEmpty(p)) {return;}//栈顶指针--p->top--;
}
- 看看栈是否为空,要是空就直接返回,就不删除了。
- 然后栈顶指针向下移动。
获取栈顶元素
//获取栈顶元素
Datatype Stacktop(Stack* p)
{//先得看看是否为空assert(p);if (StackEmpty(p)) {return;}// return ps->arr[--p->top]; // 错误写法return p->arr[p->top - 1];
}
- 先判空是否为空栈。
- 减1让我们栈顶指针指向栈顶元素。
- 然后直接把栈顶元素返回就好了。
获取栈中有效元素的个数
// 获取栈中有效元素的个数
int StackSize(Stack* p)
{//检测参数合法性assert(p);return p->top;
}
直接把top输出传回来就好了。
检测栈是否为空
// 检测栈是否为空,如果为空返回真,否则返回假
int StackEmpty(Stack* p)
{//检测参数合法性assert(p);return 0 == p->top;
}
- 判断是否为空其实就是栈顶指针是否等于栈底指针。
- 这里我们0就是栈底指针 top就是栈顶指针相等就是空。
栈的销毁
//栈的销毁
void StackDestroy(Stack* p)
{//检测参数合法性assert(p);//free掉防止内存泄露if (p->arr) {free(p->arr);p->capacity = 0;p->top = 0;}
}
- 先检验参数合法性。
- 把这个栈free掉。
- 再把参数更新。
扩容
//扩容
//先申请新的内存空间
//把原来的数据拷贝到新扩容的空间里面去
//free掉原来空间,让arr指向新开辟的内存空间
void StackCheckCapacity(Stack* p)
{//检测参数合法性assert(p);if (p->capacity == p->top) {int Newcapacity = (p->capacity << 1);Datatype* temp = (Datatype*)malloc(sizeof(Datatype) * Newcapacity);if (NULL == temp) {assert(0);}memcpy(temp, p->arr, sizeof(Datatype) * p->capacity);free(p->arr);p->arr = temp;p->capacity = Newcapacity;}
}
- 开辟新的内存空间。
- 把数据拷贝到新空间去。
- 释放旧空间。
- p的arr指向新空间。
测试
void text() {Stack s;StackInit(&s, 3);StackPush(&s, 1);StackPush(&s, 2);StackPush(&s, 3);printf("size = %d\n", StackSize(&s));printf("top = %d\n", Stacktop(&s));StackPush(&s, 4); // 扩容StackPush(&s, 5);StackPush(&s, 6);StackPush(&s, 7); // 扩容printf("size = %d\n", StackSize(&s));printf("top = %d\n", Stacktop(&s));StackPop(&s);StackPop(&s);StackPop(&s);printf("size = %d\n", StackSize(&s));printf("top = %d\n", Stacktop(&s));StackDestroy(&s);
}
数据结构 严薇敏 栈 的实现及其使用方法详解相关推荐
- 数据结构 严薇敏 堆 的实现及其使用方法详解
1.堆的概念 将一个关键码的集合K = {k0 , k1,k2,k3--kn-1}把他所有元素按完全二叉树的存储方式放在一个一维数组中,并且满足双亲节点大于孩子节点,或者双亲节点小于孩子节点将根节点最 ...
- 数据结构 严薇敏 队列 的实现及其使用方法详解
目录 1.队列 1.1队列的概念及结构 1.2队列的实现 1.3接口以及实现 Queue.h Queue.c 申请一个队列的节点 初始化队列 入队列 出队列 查找队头元素 查找队尾元素 获取队列长度 ...
- c语言栈是什么线性表,数据结构严薇敏——栈的顺序存储(C语言)
栈是限定只能在表尾进行插入和删除操作的线性表. 栈的特点是后进先出. 它的顺序数据结构定义为 typedef struct SQSTACK { ElemType *base; ElemType *to ...
- 数据结构 严薇敏 顺序表的实现(增 删 改)及其使用方法详解
时间复杂度 数据结构 时间复杂度和空间复杂度 目录 1.线性表 2.顺序表 2.1概念及结构 2.2 接口实现 SeqList.h SeqList.c 2.2.1初始化链表以及销毁链表的实现 初始化顺 ...
- Mr.J--C语言头函数的建立(附严薇敏《数据结构》线性表代码)
如何正确编写 C 语言头文件和与之相关联的 c 源程序文件 查看此文章需要有一定的C语言编程基础 首先就要了解它们的各自功能.要理解C 文件与头文件(即.h)有什么 不同之处,首先需要弄明白编译器的工 ...
- 数据结构:栈(stack容器)使用详解
栈(stack容器)使用详解 一.栈的基本概念 1. 栈的基本定义 2.栈的相关概念 3.栈的常用操作 二.栈的操作应用 UVA514 铁轨 Rails 题目描述 输入格式 输出格式 题目翻译 题目分 ...
- wringPi 初始化GPIO 为上拉_敏矽微电子Cortex-M0学习笔记04-GPIO详解及应用实例
前面我们已经对敏矽微电子的基于cortex m0内核的ME32F030R8T6的基本功能做了介绍,然后详细讲解了开发环境MDK的安装,pack包的安装,工程的建立及程序的仿真,紧接着讲解了ME32F0 ...
- 数据结构:栈和队列(Stack Queue)【详解】
友情链接:数据结构专栏 目录 栈和队列 [知识框架] 栈 一.栈的基本概念 1.栈的定义 2.栈的常见基本操作 二.栈的顺序存储结构 1.栈的顺序存储 2.顺序栈的基本算法 (1)初始化 (2)判栈空 ...
- 【数据结构基础整理】图--06:克鲁斯卡尔算法详解
详解最小生成树中的克鲁斯卡尔算法 0x01.关于克鲁斯卡尔算法 Kruskal算法是一种用来查找最小生成树的算法,由Joseph Kruskal在1956年发表.克鲁斯卡尔算法主要针对边集数组展开. ...
最新文章
- 华为程序员发现孩子不是自己的!怒提离婚!但老婆只要房子车子!不要孩子!绿他的竟然是个酒吧混混!...
- Nginx配置——搭建 Nginx 高可用集群(双机热备)
- vSphere vCenter 4.0 安装图解
- 神奇的幻方(NOIP2015)(真·纯模拟)
- 在PPT的时候,发现用Python十几行代码就可以实现Logo换色
- How To Make JMeter Behave More Like A Real Browser
- 结合 AOP 轻松处理事件发布处理日志
- 开源 免费 java CMS - FreeCMS1.3-数据对象-report
- 一个项目涉及到的50个Sql语句
- GNU C getopt()、getopt_long() 与 getopt_long_only() 获取命令行参数
- 正则表达式验证首尾是空格的字符串
- python如何执行代码_在Python中重新运行代码块
- 数学 平面内 两直线 两个向量的夹角计算公式 C++实现
- 【Android Studio 3.5.3】蓝牙串口及USB串口例程
- 软考 - 软件设计师 - 完整知识点笔记 - 按考频整理
- matlab 对话框大小调整,matlab界面设计---对话框设计
- cython使用初步
- word文档自动保存方法
- 数据分析师必须掌握的 十三大数据分析方法论!
- 行列式因子、不变因子、初等因子、smith标准型、Jordan标准型、最小多项式的matlab实现