勤于总结,持续输出!

1.栈

1.1栈的定义

栈(stack)是限定在表尾进行插入和删除的操作的线性表。

我们把允许插入和删除的一端称为栈顶(top),另一端称为栈底(bottom),不包含任何数据元素的栈称为空栈。栈又称为后进先出(Last In First Out)的线性表,简称LIFO结构。

栈的插入操作,叫做进栈,也称压栈、入栈。

栈的删除操作,叫做出栈,也称弹栈。

1.2栈的顺序存储结构及实现

既然栈是线性表的特例,那么栈的顺序存储其实也是线性表顺序存储的简化。

用数组实现,下标为0的一端作为栈底比较好,因为首元素都存在栈底。

栈的结构定义:

定义一个top变量来指示栈顶元素在数组中的位置,若存储栈的长度为SackSize,则栈顶位置top必须小于SackSize。当栈存在一个元素时,top等于0,因此通常把空栈的判定条件为top=-1。

typedef int SElemType;
typedef struct
{
SElemType data[MAXSIZE];
int top; /*用于栈顶指针*/
} SqStack;

1.3栈的顺序存储结构——进栈操作

代码实现:

#define MAXSIZE 5
#define OK 1
#define ERROR 0 /*插入元素e为新的栈顶元素*/
Status Push(SqStack *S, SElemType e)
{
if (S->top == MAXSIZE - 1) /*栈满*/
{
return ERROR;
}
S->top++;
S->data[S->top] = e;
return OK;
}

测试代码:

int main()
{
SqStack stack = { {1,2},1 }; /*初始化栈内有两个元素,top=1*/
Push(&stack, 3);
}

运行结果:

1.4栈的顺序存储结构——出栈操作

代码实现:

#define MAXSIZE 5
#define OK 1
#define ERROR 0 /*若栈不为空,则删除S的栈顶元素,用e返回其值*/
Status Pop(SqStack *S, SElemType *E)
{
if (S->top == -1)
{
return ERROR;
}
*E = S->data[S->top];
S->data[S->top] = NULL;
S->top--;
return OK;
}

测试代码:

int main()
{
SElemType e;
SqStack stack = { {1,2},1 }; /*初始化栈内有两个元素,top=1*/
Push(&stack, 3);
Pop(&stack, &e);
}

运行结果:

验证了栈是后进先出的结构。

1.5栈的链式存储结构及实现

栈的链式存储结构,简称为栈链。由于单链表有头指针,而栈顶指针也是必须的,那么便可以让它俩合二为一。以为就是说栈顶放在单链表的头部。

对于链栈来说,基本不存在栈满的情况,除非内存已经没有可以使用的空间。但是对于空栈来说,链表原定义是头指针指向空,那么链栈的空其实就是top=NULL。

栈链的结构代码如下:

typedef int SElemType;
typedef struct StackNode
{
SElemType data;
struct StackNode *next;
} StackNode;
typedef struct StackNode *LinkStackPtr; typedef struct LinkStatck
{
LinkStackPtr top;
int count;
}LinkStatck;

1.6栈的链式存储结构——进栈操作

代码实现:

#define OK 1
#define ERROR 0
typedef int Status;
typedef int SElemType; /*插入元素e为新的栈顶元素*/
Status Push(LinkStatck *S, SElemType e)
{
LinkStackPtr s = (LinkStackPtr)malloc(sizeof(StackNode));
s->data = e;
s->next = S->top;
S->top = s; /*将新的节点s赋值给栈顶指针*/
S->count++;
return OK;
}

测试代码:

int main()
{
LinkStatck stack = { NULL ,0}; /*初始化一个空链栈*/
Push(&stack, 1);
Push(&stack, 2);
Push(&stack, 3);
}

运行结果:

动画模拟:

1.7栈的链式存储结构——出栈操作

代码实现:

#define OK 1
#define ERROR 0
typedef int Status;
typedef int SElemType; /*若栈不为空,则删除S的栈顶元素,用e返回其值*/
Status Pop(LinkStatck *S, SElemType *e)
{
LinkStackPtr p;
if (S->count == 0)
{
return ERROR;
}
*e = S->top->data;
p = S->top; /*将栈顶节点赋值给p*/
S->top = S->top->next; /*使栈顶指针下移一位,指向后一节点*/
free(p); /*释放节点p*/
S->count--;
return OK;
}

测试代码:

int main()
{
LinkStatck stack = { NULL ,0}; /*初始化一个空链栈*/
Push(&stack, 1);
Push(&stack, 2);
Push(&stack, 3);
SElemType e;
Pop(&stack, &e);
Pop(&stack, &e);
Pop(&stack, &e);
}

运行结果:

动画模拟:

2.队列

2.1队列的定义

队列(queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。

队列是一种先进先出(First In First Out)的线性表,简称FIFO。允许插入的一端称为队尾,允许删除的一端称为队头。

2.2队列的顺序存储结构

我们假设一个队列有n个元素,则顺序存储的队列需建立一个大于n的数组。

现在进行入队操作,就是在队尾插入一个元素,不需要移动任何元素,因此时间复杂度是O[1]。

出队操作是在队头,那么队列中所有的元素都要向前移动一个位置,确保下标为0的位置不为空,时间复杂度是O[n],这是个问题。

如果不限定出队操作时所有的元素都要向前移动,也就是说队头不一定必须在下标为0 的位置,出队的性能就会大大增加。

但是这样又会出现另一个问题——假溢出,就是假设队列前面的位置是空着的,但是从队尾入队已经满了。

循环队列可以解决这一个问题,后面满了,就从头再开始,也就是头尾相接的循环,这种头尾相接的顺序存储结构称为循环队列。

但是循环队列还是会面临着数组溢出的问题。

2.3队列的链式存储结构及实现

队列的链式存储结构,其实就是线性表的单链表,只不过它能尾进头出而已,简称链队列。

队头指针指向链队列的头节点,而队尾指针指向终端节点:

空队列时都指向头节点:

链队列的结构如下:

typedef int QElemType;
typedef struct QNode /*结点结构*/
{
QElemType data;
struct QNode *next;
}QNode,*QueuePtr; typedef struct /*队列的链表结构*/
{
QueuePtr front, rear; /*队头、队尾指针*/
} LinkQueue;

2.4队列的链式存储结构——入队操作

入队操作,在队尾插入新元素。

代码实现:

#define OK 1
#define ERROR 0 typedef int Status;
/*插入元素e为Q的新的队尾元素*/
Status EnQueue(LinkQueue *Q, QElemType e)
{
QueuePtr s = (QueuePtr)malloc(sizeof(QNode));
s->data = e;
s->next = NULL; Q->rear->next = s; /*把拥有元素e新节点s赋值给原队尾结点的后继*/
Q->rear = s; /*把s设置为队尾结点,rear指向s*/ return OK;
}

测试代码:

int main()
{
/*头结点*/
QueuePtr head = (QueuePtr)malloc(sizeof(QNode));
head->data = 0;
head->next = NULL; LinkQueue q = { head ,head }; //空队列,队头、队尾指针都指向头结点 EnQueue(&q, 1);
EnQueue(&q, 2);
}

运行结果:

动画模拟:

2.4队列的链式存储结构——出队操作

代码实现:

#define OK 1
#define ERROR 0 typedef int Status;
/*若队列不为空,删除Q的队头元素,用e返回其值*/
Status DeQueue(LinkQueue *Q, QElemType *e)
{
QueuePtr p;
if (Q->front == Q->rear)
{
return ERROR;
}
p = Q->front->next; /*将欲删除的队头节点暂存给p*/
*e = p->data;
Q->front->next = p->next; /*将原队头结点后继赋值给头结点后继*/ if (Q->rear == p) /*若队头是队尾,则删除后将rear指向头结点*/
{
Q->rear = Q->front;
} free(p);
return OK;
}

测试代码:

int main()
{
/*头结点*/
QueuePtr head = (QueuePtr)malloc(sizeof(QNode));
head->data = 0;
head->next = NULL; LinkQueue q = { head ,head }; EnQueue(&q, 1);
EnQueue(&q, 2);
QElemType e;
DeQueue(&q, &e);
}

运行结果:

动画模拟:

参考:《大话数据结构》


本文为博主学习感悟总结,水平有限,如果不当,欢迎指正。

如果您认为还不错,不妨点击一下下方的【推荐】按钮,谢谢支持。

转载与引用请注明出处。

【图解数据结构】 栈&队列的更多相关文章

  1. 数据结构 栈&队列

    2-4 依次在初始为空的队列中插入元素a,b,c,d以后,紧接着做了两次删除操作,此时的队头元素是( ) 删除,移动头指针: 增加,移动尾指针: 删除a,b ,队头c 2-3 在一个链队列中,fron ...

  2. 数据结构之队列and栈总结分析

    一.前言: 数据结构中队列和栈也是常见的两个数据结构,队列和栈在实际使用场景上也是相辅相成的,下面简单总结一下,如有不对之处,多多指点交流,谢谢. 二.队列简介 队列顾名思义就是排队的意思,根据我们的 ...

  3. 数据结构和算法(Golang实现)(14)常见数据结构-栈和队列

    栈和队列 一.栈 Stack 和队列 Queue 我们日常生活中,都需要将物品排列,或者安排事情的先后顺序.更通俗地讲,我们买东西时,人太多的情况下,我们要排队,排队也有先后顺序,有些人早了点来,排完 ...

  4. java 集合 Connection 栈 队列 及一些常用

    集合家族图 ---|Collection: 单列集合 ---|List: 有存储顺序 , 可重复 ---|ArrayList: 数组实现 , 查找快 , 增删慢 ---|LinkedList: 链表实 ...

  5. Java 容器之 Connection栈队列及一些常用

    集合家族图 ---|Collection: 单列集合 ---|List: 有存储顺序 , 可重复 ---|ArrayList: 数组实现 , 查找快 , 增删慢 ---|LinkedList: 链表实 ...

  6. C++ 泛型 编写的 数据结构 栈

    平时编程里经常需要用到数据结构,比如  栈和队列 等,  为了避免每次用到都需要重新编写的麻烦现将  C++ 编写的 数据结构   栈   记录下来,以备后用. 将 数据结构  栈   用头文件的形式 ...

  7. java面向对象的栈 队列 优先级队列的比较

    栈 队列 有序队列数据结构的生命周期比那些数据库类型的结构(比如链表,树)要短得多.在程序操作执行期间他们才被创建,通常用他们去执行某项特殊的任务:当完成任务之后,他们就会被销毁.这三个数据结构还有一 ...

  8. JavaScript数据结构——栈的实现与应用

    在计算机编程中,栈是一种很常见的数据结构,它遵从后进先出(LIFO——Last In First Out)原则,新添加或待删除的元素保存在栈的同一端,称作栈顶,另一端称作栈底.在栈中,新元素总是靠近栈 ...

  9. javascript数据结构之队列

    首先什么是队列? 排队买东西就是生活中队列的实际例子,在队伍中大家必须按照顺序来,不能插队,新来的人只能排在队伍的最后面.新加入的人相当于队列的后端加入的元素,队伍最前面买完东西的人离开队伍相当于是队 ...

  10. 栈 & 队列

    栈 先进者后出,后进者先出,LIFO,典型的"栈"结构 从栈的操作特性上来看,栈是一种"操作受限"的线性表,只允许在一段插入和删除数据. 在功能上来说,数组和链 ...

随机推荐

  1. .NET Core快速入门教程 5、使用VS Code进行C#代码调试的技巧

    一.前言 为什么要调试代码?通过调试可以让我们了解代码运行过程中的代码执行信息,比如变量的值等等.通常调试代码是为了方便我们发现代码中的bug.ken.io觉得熟练代码调试技巧是成为合格程序员的基本要 ...

  2. Android实用代码七段(三)

    正文  一.获取已经安装APK的路径 PackageManager pm = getPackageManager(); for (ApplicationInfo app : pm.getInstall ...

  3. android scrollview 属性

     理论部分1.ScrollView和HorizontalScrollView是为控件或者布局添加滚动条2.上述两个控件只能有一个孩子,但是它并不是传统意义上的容器3.上述两个控件可以互相嵌套4.滚动条 ...

  4. Beta冲刺第三天

    一.昨天的困难 没有困难. 二.今天进度 1.林洋洋:修改权限相关的资源表示,修复flex布局排版高度问题,修复文件更新问题,去除登录页面的默认账号密码,服务器部署. 2.黄腾达:修复日程首次执行时间 ...

  5. 1013团队Beta冲刺day4

    项目进展 李明皇 今天解决的进度 因服务器端未完成登录态维护,故无法进行前后端联动. 明天安排 前后端联动调试 林翔 今天解决的进度 因上课和实验室事务未完成登录态维护 明天安排 完成登录态维护 孙敏 ...

  6. 20162328蔡文琛week04

    学号 20162328 <程序设计与数据结构>第4周学习总结 教材学习内容总结 本周学习了第四章和第七章,第四章中的内容已经有了初步定的掌握,布尔表达式的运用,是条件和循环语句的基础及数组 ...

  7. xcode7,ios9 部分兼容设置

    神奇的苹果公司,再一次让程序员中枪. 一.xcode7 新建的项目,Foundation下默认所有http请求都被改为https请求. HTTP+SSL/TLS+TCP = HTTPS 也就是说,服务 ...

  8. 【iOS】swift-文字宽度的计算

    如图所示,需要sectionView的标题宽度可以动态变化 举例说明: 只需在tableView的代理方法 func tableView(tableView: UITableView, viewFor ...

  9. 构建微服务开发环境4————安装Docker及下载常用镜像

    [内容指引] 下载Docker: Mac下安装Docker: Windows下安装Docker; 下载常用docker镜像. 一.下载Docker 1.Mac适用Docker下载地址:https:// ...

  10. D的下L

    D的小L 时间限制:4000 ms  |  内存限制:65535 KB 难度:2   描述       一天TC的匡匡找ACM的小L玩三国杀,但是这会小L忙着哩,不想和匡匡玩但又怕匡匡生气,这时小L给 ...