当前位置: 首页 > news >正文

数据结构----栈

一丶概念

          只能在一端进行插入和删除操作的线性表(又称为堆栈),进行插入和删除操作的一端称为栈顶,另一端称为栈底

二丶特点

        先进后出 FILO first in last out
        后进先出 LIFO last in first out

三丶顺序栈

     逻辑结构:线性结构
     存储结构:顺序存储
     操作:入栈、出栈

1.创建一个空的栈

2.入栈

3.出栈

       
#include <stdio.h>
#include <stdlib.h>
typedef int datatype;
typedef struct seqstack
{int maxlen;     // 数组中元素总个数datatype *data; // 指向数组的指针int top;        // 栈顶元素的下表
} seqstack_t;
seqstack_t *CreateEplist(int len)//创建一个空表
{seqstack_t *p = (seqstack_t *)malloc(sizeof(seqstack_t));//先对结构体指针开辟堆区空间if (NULL == p)//判错{printf("Create err");return NULL;}p->maxlen = len;p->top = -1;//初始化结构体p->data = (int *)malloc(sizeof(int) * len);//对指向数组的指针开辟堆区空间if (NULL == p->data)//判错{printf("DATA err");return NULL;}return p;
}
int Isfull(seqstack_t *p)//判断结构体是否为满
{return p->top + 1 == p->maxlen;
}
int IsEmpty(seqstack_t *p)//判断结构体是否为空
{return p->top == -1;
}
int Pushdata(seqstack_t *p, int data)//输入数据,入栈
{if (Isfull(p)){printf("Seqstack is full");return -1;}p->top++;p->data[p->top] = data;return 0;
}
int show(seqstack_t *p)//输出数据,出栈
{if (IsEmpty(p)){printf("Seqstack is empty");return -1;}while (!IsEmpty(p)){p->top--;printf("%d ",p->data[p->top + 1]);}printf("\n");
}
void Clearlist(seqstack_t *p)//清空栈
{p->top = -1;
}
int main(int argc, char const *argv[])
{seqstack_t *p = CreateEplist(10);Pushdata(p, 1);Pushdata(p, 2);Pushdata(p, 3);Pushdata(p, 4);Pushdata(p, 5);show(p);printf("%d\n", p->top);printf("%d\n", p->maxlen);return 0;
}

练习:
 

1. 若进栈顺序为 1,2,3,4 一下四种情况不可能出现的出栈序列是( )

      A. 1,4,3,2                B. 2,3,4,1               C. 3,1,4,2              D. 3,4,2,1

2. 下列叙述正确的是( )

     A. 线性表是线性结构
     B. 栈与队列是非线性结构 //栈只能在一端进行插入和删除操作的线性表
     C. 线性链表是非线性结构

     D. 二叉树是线性结构 //树形结构 层次关系

3. 下列关于栈叙述正确的是( )

      A.在栈中只能插入数据//栈只能在一端进行插入和删除操作的线性表,插入和删除端称为栈顶 ,另一端是栈底
      B.在栈中只能删除数据
      C.栈是先进先出的线性表
      D.栈是先进后出的线性表

四丶链式栈

        逻辑结构:线性结构

        存储结构:链式存储
        操作:入栈、出栈

#include <stdio.h>
#include <stdlib.h>
typedef int datatype;
typedef struct linkstack
{datatype data;          // 数据域struct linkstack *next; // 指针域
} linkstack_t;
// 1.创建一个空的栈
void CreateEpLinkStack(linkstack_t **ptop)
{*ptop = NULL; // 主函数中top = NULL;
}
// 2.入栈   data是入栈的数据
//  参数上之所以采用二级指针,因为我们要随着入栈添加新的节点作为头,top需要永远指向当前链表的头,
//  那么修改main函数中的top,我们采用地址传递
int PushLinkStack(linkstack_t **ptop, datatype data)
{// 1.创建一个新节点,并初始化linkstack_t *pnew = (linkstack_t *)malloc(sizeof(linkstack_t));if (pnew == NULL){perror("PushLinkStack err");return -1;}pnew->data = data;pnew->next = NULL;// 2.将新节点头插到无头单向链表中pnew->next = *ptop;// 3.移动栈针,栈针top永远只向无头单向链表的第一个节点*ptop = pnew;return 0;
}
// 3.判断栈是否为空
int IsEpLinkStack(linkstack_t *top)
{return top == NULL;
}
// 4.出栈
datatype PopLinkStack(linkstack_t **ptop)
{// 1.容错判断if (IsEpLinkStack(*ptop)){perror("IsEpLinkStack");return -1;}// 2.定义pdel指向被删除节点linkstack_t *pdel = *ptop;// 3.定义一个变量temp保存出栈数据datatype temp = pdel->data;// 4.移动栈针(跨过被删除节点)*ptop = (*ptop)->next;// 5.释放被删除节点free(pdel);pdel = NULL;return temp;
}
// 5.清空栈
void ClearLinkStack(linkstack_t **ptop) // 用二级指针,是因为清空后需要将main函数中的top变为NULL
{while (!IsEpLinkStack(*ptop))PopLinkStack(ptop);
}
// 6.求栈的长度
int LengthLinkStack(linkstack_t *top) // 用一级指针,是因为我只是求长度,不需要修改main函数中top指针的指向
{int len = 0;// top相当于无头单向链表的头指针,求长度,遍历无头单向链表while (top != NULL){len++;top = top->next;}return len;
}
// 7.获取栈顶数据,不是出栈,不需要移动main函数中的top,所以用一级指针
datatype GetTopLinkStack(linkstack_t *top)
{if (!IsEpLinkStack(top))return top->data;return -1;
}int main(int argc, char const *argv[])
{linkstack_t *top; //CreateEpLinkStack(&top);for (int i = 1; i <= 5; i++)PushLinkStack(&top, i);printf("top value is %d\n", GetTopLinkStack(top));printf("len is %d\n", LengthLinkStack(top));while (!IsEpLinkStack(top)){printf("%d ", PopLinkStack(&top));}printf("\n");return 0;
}

总结:

顺序栈和链式栈的区别是什么?

     (1)存储结构不同,顺序栈相当于数组,连续的,链式栈 链表非连续的
     (2)顺序栈的长度受限制,而链栈不会

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • C语言指针详解-上
  • (七)Activiti-modeler中文支持
  • 『Z-Workshop』 The Graph workshop mini hackathon活动
  • IBERT 眼图机制
  • 使用Poi-tl对word模板生成动态报告
  • 利用 Python 的包管理和动态属性获取(`__init__.py` 文件和 `getattr` 函数)特性来实现工厂方法模式
  • RHEL8 配置epel源
  • 深入探讨C语言中的高级指针操作
  • 生产环境中MapReduce的最佳实践
  • 微信小程序在不同移动设备上的差异导致原因
  • Startup-SBOM:一款针对RPM和APT数据库的逆向安全工具
  • Jenkins使用Publish Over SSH插件远程部署程序到阿里云服务器
  • vue3+ts+vite+pinia+element-plus搭建一个项目
  • 使用Docker-compose一键部署Wordpress平台
  • Bean对象生命周期流程图
  • canvas 绘制双线技巧
  • iOS仿今日头条、壁纸应用、筛选分类、三方微博、颜色填充等源码
  • JavaScript 事件——“事件类型”中“HTML5事件”的注意要点
  • Java深入 - 深入理解Java集合
  • js 实现textarea输入字数提示
  • JS进阶 - JS 、JS-Web-API与DOM、BOM
  • miniui datagrid 的客户端分页解决方案 - CS结合
  • Node.js 新计划:使用 V8 snapshot 将启动速度提升 8 倍
  • PHP那些事儿
  • SQLServer之创建数据库快照
  • Zepto.js源码学习之二
  • 阿里云前端周刊 - 第 26 期
  • 产品三维模型在线预览
  • 二维平面内的碰撞检测【一】
  • 服务器之间,相同帐号,实现免密钥登录
  • 和 || 运算
  • 力扣(LeetCode)357
  • 前端js -- this指向总结。
  • 人脸识别最新开发经验demo
  • 使用 @font-face
  • 跳前端坑前,先看看这个!!
  • 线上 python http server profile 实践
  • 异步
  • 用Canvas画一棵二叉树
  • 用quicker-worker.js轻松跑一个大数据遍历
  • 找一份好的前端工作,起点很重要
  • 终端用户监控:真实用户监控还是模拟监控?
  • 转载:[译] 内容加速黑科技趣谈
  • 数据库巡检项
  • ​一文看懂数据清洗:缺失值、异常值和重复值的处理
  • ######## golang各章节终篇索引 ########
  • #基础#使用Jupyter进行Notebook的转换 .ipynb文件导出为.md文件
  • $().each和$.each的区别
  • $.ajax中的eval及dataType
  • ( )的作用是将计算机中的信息传送给用户,计算机应用基础 吉大15春学期《计算机应用基础》在线作业二及答案...
  • (02)Hive SQL编译成MapReduce任务的过程
  • (二)斐波那契Fabonacci函数
  • (非本人原创)史记·柴静列传(r4笔记第65天)
  • (非本人原创)我们工作到底是为了什么?​——HP大中华区总裁孙振耀退休感言(r4笔记第60天)...
  • (附源码)ssm高校社团管理系统 毕业设计 234162