1 栈

1.1 栈的基本概念

栈(stack)又名堆栈,它是一种 运算受限的线性表。限定 仅在表尾进行插入和删除操作 的线性表。表尾被称为栈顶,相对地,把另一端称为栈底。

1.1.1 特点

它的特殊之处在于限制了这个线性表的插入和删除的位置,它始终只在栈顶进行。这也就使得:栈底是固定的,最先进栈的只能在栈底。

1.2 栈的常用操作

  • 创建栈

  • 销毁栈

  • 清空栈

  • 进栈

  • 出栈

  • 获取栈顶元素

  • 获取栈的大小

1.2.1 栈的抽象数据类型

ADT 栈(stack)

Data
通线性表。元素具有相同的类型,相邻的元素具有前驱和后继关系。 Operation
// 初始化,建立一个空栈S
InitStack(*S);
// 若栈存在,则销毁它
DestroyStack(*S);
// 将栈清空
ClearStack(*S);
// 若栈为空则返回true,否则返回false
StackEmpty(S);
// 若栈存在且非空,用e返回S的栈顶元素
GetTop(S,*e);
// 若栈S存在,插入新元素e到栈S中并成为其栈顶元素
Push(*S,e);
// 删除栈S中的栈顶元素,并用e返回其值
Pop(*S, *e);
// 返回栈S的元素个数
StackLength(S); endADT

1.3 栈的顺序存储

1.3.1 基本概念

基本概念

栈的顺序存储结构简称顺序栈,它是运算受限制的顺序表。顺序栈的存储结构是:利用一组地址连续的的存储单元依次存放自栈底到栈顶的数据元素,同时附设指针top只是栈顶元素在顺序表中的位置。

栈是先进后出的线性表。

1.3.2 设计与实现

因为栈是一种特殊的线性表,所以栈的顺序存储可以通过顺序线性表来实现。

示例代码:

SqStack.h

#ifndef _SQSTACK_H
#define _SQSTACK_H #define MAXSIZE 50 typedef int EnumType; typedef struct _SQSTACK
{
int top; // 栈顶指针
EnumType data[MAXSIZE];
}SqStack; // 初始化,建立一个空栈S
void InitStack(SqStack *S); // 将栈清空
void ClearStack(SqStack *S); // 若栈为空则返回true,否则返回false
int StackEmpty(SqStack S); // 若栈存在且非空,用e返回S的栈顶元素
void GetTop(SqStack S, EnumType *e); // 若栈S存在,插入新元素e到栈S中并成为其栈顶元素
void Push(SqStack *S, EnumType e); // 删除栈S中的栈顶元素,并用e返回其值
void Pop(SqStack *S, EnumType *e); // 返回栈S的元素个数
int StackLength(SqStack S); #endif // _SQSTACK_H

SqStack.c

#include "SqStack.h"

#include <string.h>

void InitStack(SqStack *S)
{
// 空栈
S->top = -1; memset(S->data, 0, sizeof(S->data));
} void ClearStack(SqStack *S)
{
S->top = -1;
} int StackEmpty(SqStack S)
{
if (S.top == -1)
{
return 1;
} return 0;
} void GetTop(SqStack S, EnumType *e)
{
// 栈为空
if (S.top == -1 && S.data[S.top]!= 0)
{
return;
} *e = S.data[S.top];
} void Push(SqStack *S, EnumType e)
{
// 栈已经满了
if (S->top == MAXSIZE - 1)
{
return;
} // 栈顶上移
S->top++;
// 赋值
S->data[S->top] = e;
} void Pop(SqStack *S, EnumType *e)
{
// 栈为空
if (S->top == -1 && S->data[S->top]!= 0)
{
return;
} // 赋值
*e = S->data[S->top];
// 栈顶指针下移
S->top--;
} int StackLength(SqStack S)
{
return S.top + 1;
}

main.c

#include "SqStack.h"

#include <stdio.h>
#include <stdlib.h> void main()
{
// 定义栈变量
SqStack st; int i = -1; // 初始化栈
InitStack(&st); // 压栈
for (i = 0; i < 10; ++i)
{
Push(&st,i+1);
} printf("stack size = %d\n", StackLength(st)); // 出栈
while (StackEmpty(st) != 1)
{
int temp; // 取栈顶元素
GetTop(st, &temp);
printf("Get stacktop elem is: %d\n", temp); // 删除栈顶元素
Pop(&st, &temp);
printf("Delete stacktop elem is: %d\n", temp);
} system("pause");
}

运行结果:

1.4 栈的链序存储

1.4.1 基本概念

栈的链式存储结构简称链栈。

1.4.2 设计与实现

链栈是一种特殊的线性表,链栈可以通过链式线性表来实现。

示例代码:

LinkStack.h

#ifndef _LINKSTACK_H
#define _LINKSTACK_H // 定义小链表节点
typedef struct NODE
{
struct NODE* next;
}Node; // 链表结构体
typedef struct
{
// 栈顶指针
Node *top;
// 长度
int length;
}LinkStack; // 初始化,建立一个空栈S
void InitStack(LinkStack *S); // 将栈清空
void ClearStack(LinkStack *S); // 若栈为空则返回true,否则返回false
int StackEmpty(LinkStack S); // 若栈存在且非空,用e返回S的栈顶元素
void GetTop(LinkStack S, Node **e); // 若栈S存在,插入新元素e到栈S中并成为其栈顶元素
void Push(LinkStack *S, Node *e); // 删除栈S中的栈顶元素,并用e返回其值
void Pop(LinkStack *S, Node **e); // 返回栈S的元素个数
int StackLength(LinkStack S); #endif // _LINKSTACK_H

LinkStack.c

#include "LinkStack.h"

#include <stdio.h>

void InitStack(LinkStack *S)
{
S->length = 0;
S->top = NULL;
} void ClearStack(LinkStack *S)
{
while (S->length)
{
Node* p; Pop(S, &p);
}
} int StackEmpty(LinkStack S)
{
if (S.length == 0)
{
return 1;
} return 0;
} void GetTop(LinkStack S, Node **e)
{
// 空栈
if (S.length == 0 || S.top == NULL)
{
return;
} *e = S.top;
} // 栈顶是链表头部
void Push(LinkStack *S, Node *e)
{
// 节点e插入到链表的头部
e->next = S->top;
// top指针指向第一个节点
S->top = e;
// 长度+1
S->length++;
} void Pop(LinkStack *S, Node **e)
{
// 删除第一个节点
Node* pDel = S->top; // 空栈
if (S->length == 0)
{
return;
} // 赋值
*e = pDel;
// 栈顶指针后移
S->top = pDel->next;
// 长度减1
S->length--;
} int StackLength(LinkStack S)
{
return S.length;
}

main.c

#include <stdio.h>
#include <stdlib.h> #include "LinkStack.h" // 业务节点
typedef struct stu
{
// 包含链表节点
Node node;
int id;
int age;
}Student; void main()
{
Student stu[10];
// 链表结构变量
LinkStack st; int i = -1; // 初始化栈
InitStack(&st); // 初始化数组
for (i = 0; i < sizeof(stu) / sizeof(Student); ++i)
{
stu[i].id = i;
stu[i].age = i + 20; // 数据添加链表中
Push(&st, &stu[i].node); printf("stack size = %d\n", StackLength(st)); while (StackEmpty(st) != 1)
{
Node* p = NULL; Student* pp = NULL; // 获取栈顶元素
GetTop(st, &p); pp = (Student*)p; printf("elem id = %d, age=%d\n", pp->id, pp->age); // 删除
Pop(&st, &p); pp = (Student*)p; printf("Delete elem id = %d, age=%d\n", pp->id, pp->age);
}
} system("pause");
}

运行结果:

2 队列

2.1 基本概念

队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。

2.1.1 特点

队列是先进先出的线性表。

在队尾添加元素,在队头删除元素。

判断队列是空队列还是已满呢?

  1. 栈空: 队首标志 = 队尾标志时,表示栈空。

  2. 栈满 : 队尾 + 1 = 队首时,表示栈满。

2.2 队列的常用操作

  • 创建队列

  • 销毁队列

  • 清空队列

  • 进队列

  • 出队列

  • 获取队头元素

  • 获取队列的长度

2.2.1 队列的抽象数据类型

ADT 队列(Queue)

Data
通线性表。元素具有相同的类型,相邻元素具有前驱后继关系。 Operation
// 初始化操作,建立一个空队列Q
InitQueue(*Q);
// 若队列Q存储,则销毁它。
DestroyQueue(*Q);
// 将队列Q清空
ClearQueue(*Q);
// 若队列为空则返回true,否则返回false
QueueEmpty(Q);
// 若队列Q存在且非空,用e返回队列Q的队头元素
GetHead(Q, *e);
// 若队列Q存在,插入新元素e到队列Q中并成为队尾元素。
EnQueue(*Q, e);
// 删除队列Q中的队头元素,并用e返回其值
DeQueue(*Q, *e);
// 返回队列Q的元素个数
QueueLength(Q); endADT

2.3 队列顺序模型和链表模型关系分析

2.4 队列的顺序存储

2.4.1 基本概念

队列也是一种特殊的线性表;可以用线性表顺序存储来模拟队列。

2.4.2 设计与实现

示例代码:

SqQueue.h

#ifndef _SQQUEUE_H
#define _SQQUEUE_H #define MAXSIZE 50 typedef int EnumType; typedef struct _SQQUEUE
{
// 尾节点指针
int rear;
// 头结点指针
int front; EnumType data[MAXSIZE];
}SqQueue; // 初始化操作,建立一个空队列Q
void InitQueue(SqQueue *Q); // 将队列Q清空
void ClearQueue(SqQueue *Q); // 若队列为空则返回true,否则返回false
int QueueEmpty(SqQueue Q); // 若队列Q存在且非空,用e返回队列Q的队头元素
void GetHead(SqQueue Q, EnumType* e); // 若队列Q存在,插入新元素e到队列Q中并成为队尾元素。
void EnQueue(SqQueue *Q, EnumType e); // 删除队列Q中的队头元素,并用e返回其值
void DeQueue(SqQueue *Q, EnumType* e); // 返回队列Q的元素个数
int QueueLength(SqQueue Q); #endif //_SQQUEUE_H

SqQueue.c

#include "SqQueue.h"

#include <string.h>

void InitQueue(SqQueue *Q)
{
Q->rear = Q->front = 0; memset(Q->data, 0, sizeof(Q->data));
} void ClearQueue(SqQueue *Q)
{
Q->rear = Q->front = 0; memset(Q->data, 0, sizeof(Q->data));
} int QueueEmpty(SqQueue Q)
{
if (Q.rear == Q.front)
{
return 1;
} return 0;
} // 返回队首元素的值,但不删除该元素
void GetHead(SqQueue Q, EnumType* e)
{
// 队列为空
if (Q.rear == Q.front)
{
return;
} *e = Q.data[Q.front];
} // 在队尾压入新元素
void EnQueue(SqQueue *Q, EnumType e)
{
// 队列已经满了
if (Q->rear -1 == MAXSIZE)
{
return;
}
else
{
// 赋值
Q->data[Q->rear] = e;
// 队尾上移
Q->rear++;
}
} // 删除队列首元素
void DeQueue(SqQueue *Q, EnumType* e)
{
// 队列为空
if (Q->rear == Q->front)
{
return;
} // 赋值
*e = Q->data[Q->front];
// front指针上移
Q->front++;
} int QueueLength(SqQueue Q)
{
return Q.rear;
}

main.c

#include "SqQueue.h"

#include <stdio.h>
#include <stdlib.h> void main()
{
// 队列变量
SqQueue q; int i = -1; // 初始化队列
InitQueue(&q); // 入队列
for (i = 0; i < 5; ++i)
{
EnQueue(&q, i+1);
} printf("Queue size = %d\n", QueueLength(q)); // 删除全部节点
while (QueueEmpty(q) != 1)
{
int temp; // 取栈顶元素
GetHead(q, &temp);
printf("Queue head value = %d\n",temp); // 删除栈顶元素
DeQueue(&q, &temp);
printf("Delete stacktop elem is: %d\n", temp);
} system("pause");
}

运行结果:

2.5 队列的链序存储设计与实现

2.5.1 基本概念

队列也是一种特殊的线性表;可以用线性表链式存储来模拟队列的链式存储。

2.5.2 设计与实现

示例代码:

LinkQueue.h

#ifndef _LINKQUEUE_H
#define _LINKQUEUE_H typedef struct _NODE
{
struct _NODE* next;
}Node; typedef struct
{
// 长度
int length;
// 尾节点指针
Node *rear;
// 头结点指针
Node *front;
}LinkQueue; // 初始化操作,建立一个空队列Q
void InitQueue(LinkQueue *Q);
// 将队列Q清空
void ClearQueue(LinkQueue *Q);
// 若队列为空则返回true,否则返回false
int QueueEmpty(LinkQueue Q);
// 若队列Q存在且非空,用e返回队列Q的队头元素
void GetHead(LinkQueue Q, Node** e);
// 若队列Q存在,插入新元素e到队列Q中并成为队尾元素。
void EnQueue(LinkQueue *Q, Node* e);
// 删除队列Q中的队头元素,并用e返回其值
void DeQueue(LinkQueue *Q, Node** e);
// 返回队列Q的元素个数
int QueueLength(LinkQueue Q); #endif //_LINKQUEUE_H

LinkQueue.c

#include "LinkQueue.h"

#include <stdio.h>

void InitQueue(LinkQueue *Q)
{
Q->length = 0;
Q->rear = NULL;
Q->front = NULL;
} void ClearQueue(LinkQueue *Q)
{
while (Q->length)
{
Node* p; DeQueue(Q, &p);
}
} int QueueEmpty(LinkQueue Q)
{
if (Q.length == 0)
{
return 1;
} return 0;
} // 链表的头部为队头, 尾部为队尾
void GetHead(LinkQueue Q, Node** e)
{
// 错误处理
if (Q.length == 0)
{
return;
} *e = Q.front;
} void EnQueue(LinkQueue *Q, Node* e)
{
if (Q->length == 0)
{
// 空链表
Q->rear = Q->front = e;
}
else
{
// 新节点放到队尾
Q->rear->next = e;
// rear指向最后一个节点
Q->rear = e;
} // 长度
Q->length++;
} void DeQueue(LinkQueue *Q, Node** e)
{
if (Q->length == 0)
{
// 空链表
return;
} // 赋值
*e = Q->front;
// front指针后移
Q->front = Q->front->next;
// 长度
Q->length--; if (Q->length == 0)
{
// 删除最后一个节点的时候, 尾指针需要指向NULL
Q->rear = NULL;
}
} int QueueLength(LinkQueue Q)
{
return Q.length;
}

main.c

#include "LinkQueue.h"

#include <stdio.h>
#include <stdlib.h> void main()
{
// 业务节点
typedef struct _tag_value
{
// 包含一个链表节点
Node node;
// 数据
int v;
}Value; Value val[5];
// 队列变量
LinkQueue q; int i = -1; // init
InitQueue(&q); for (i = 0; i < 5; ++i)
{
val[i].v = i + 20; // 入队列
EnQueue(&q, &val[i].node);
} printf("Queue size = %d\n", QueueLength(q)); // 删除全部节点
while (QueueEmpty(q) != 1)
{
// 取出队头元素
Node* p; Value* pp; GetHead(q, &p); pp = (Value*)p; printf("Queue head value = %d\n", pp->v); // 出队列
DeQueue(&q, &p); pp = (Value*)p; printf("Delete Queue head value = %d\n", pp->v);
} system("pause");
}

运行结果:

C++ 数据结构 2:栈和队列的更多相关文章

  1. 学习javascript数据结构(一)——栈和队列

    前言 只要你不计较得失,人生还有什么不能想法子克服的. 原文地址:学习javascript数据结构(一)--栈和队列 博主博客地址:Damonare的个人博客 几乎所有的编程语言都原生支持数组类型,因 ...

  2. python数据结构之栈与队列

    python数据结构之栈与队列 用list实现堆栈stack 堆栈:后进先出 如何进?用append 如何出?用pop() >>> >>> stack = [3, ...

  3. [ACM训练] 算法初级 之 数据结构 之 栈stack+队列queue (基础+进阶+POJ 1338+2442+1442)

    再次面对像栈和队列这样的相当基础的数据结构的学习,应该从多个方面,多维度去学习. 首先,这两个数据结构都是比较常用的,在标准库中都有对应的结构能够直接使用,所以第一个阶段应该是先学习直接来使用,下一个 ...

  4. python数据结构之栈、队列的实现

    这个在官网中list支持,有实现. 补充一下栈,队列的特性: 1.栈(stacks)是一种只能通过访问其一端来实现数据存储与检索的线性数据结构,具有后进先出(last in first out,LIF ...

  5. PHP数据结构:栈、队列、堆、固定数组

    数据结构:栈 队列: 堆: 固定尺寸的数组:

  6. 算法与数据结构(二) 栈与队列的线性和链式表示(Swift版)

    数据结构中的栈与队列还是经常使用的,栈与队列其实就是线性表的一种应用.因为线性队列分为顺序存储和链式存储,所以栈可以分为链栈和顺序栈,队列也可分为顺序队列和链队列.本篇博客其实就是<数据结构之线 ...

  7. 数据结构之栈和队列及其Java实现

    栈和队列是数据结构中非常常见和基础的线性表,在某些场合栈和队列使用很多,因此本篇主要介绍栈和队列,并用Java实现基本的栈和队列,同时用栈和队列相互实现. 栈:栈是一种基于“后进先出”策略的线性表.在 ...

  8. python——python数据结构之栈、队列的实现

    这个在官网中list支持,有实现. 补充一下栈,队列的特性: 1.栈(stacks)是一种只能通过访问其一端来实现数据存储与检索的线性数据结构,具有后进先出(last in first out,LIF ...

  9. JS数据结构的栈和队列操作

    数据结构:列表.栈.队列.链表.字典.散列.图和二叉查找树! 排序算法:冒牌.选择.插入.希尔.归并和快速! 查找算法:顺序查找和二分查找 在平时工作中,对数组的操作很是平常,它提供了很多方法使用,比 ...

  10. 【PHP数据结构】栈和队列的应用

    通过栈和队列的学习,我们似乎会感觉到其实数据结构还是非常简单的嘛.当然,这只是一个开始,我们从顺序表.链表开始,到现在的栈和队列,其实都是为了将来在铺路.在树和图的遍历算法中,都可以见到栈和队列的身影 ...

随机推荐

  1. Windows7 组策略错误:“未能打开这台计算机上的组策略对象。您可能没有合适的权限。”

    在 Windows 7 系统下,打开组策略时,出现 组策略错误 -- "未能打开这台计算机上的组策略对象.您可能没有合适的权限.".如下图所示: 解决方案: 1.进入"计 ...

  2. ubuntu20 make redis6

    redis 官网:https://redis.io redis 下载和编译位置: cd /opt 下载 redis: wget http://download.redis.io/releases/re ...

  3. 在nginx下导出数据库数据

    首先上干货 解决问题 set_time_limit(0); //设置脚本运行时间为不限制 因为php脚本默认时间为30秒 ini_set('memory_limit', -1); //取消脚本运行内存 ...

  4. 1.ffmpeg、ffplay、ffprobe命令使用

    1.学前知识 1.1视频码率值 码率公式: 码率(kbps)=文件大小(KB)*8/时间(秒) 所以码率和视频文件大小成正比的,不过码率超过一定值后,人眼是看不出效果的. 接下来,我们便先来学习ffm ...

  5. 利用HDFS实现ElasticSearch7.2容灾方案

    利用HDFS实现ElasticSearch7.2容灾方案 目录 利用HDFS实现ElasticSearch7.2容灾方案 前言 快照版本兼容 备份集群 HDFS文件系统 软件下载 JDK环境 配置系统 ...

  6. Windows 上的苹果 mac Time Machine 时间机器免费替代品 FreeFileSync 操作指南

    Windows 上的苹果 mac Time Machine 时间机器免费替代品 FreeFileSync 操作指南 前言:为什么不用 Windows 10 自带的备份还原呢?因为不稳定,不能很好的备份 ...

  7. 【学习笔记】陀螺 Treap

    以下来自一堆人从食堂走回机房时的 yy \(\Huge{强烈谴责\ \mathrm{s\color{red}{kyh}}\ 看博客不留评论的行为}\) 听说 longdie 要爆砍 FHQ 无旋 Tr ...

  8. 在windows2003上安装itunes

    本人使用windows server 2003系统 安装itunes时提示 AppleMobileDeviceSupport 只能按照在xp系统上或以上版本,你可以忽略这个错误.继续安装吧. 这样除了 ...

  9. shell中将带分隔符的字符串转为数组

    shell中将字符串列表转换成数组,需要将数组用括号来表示,元素用"空格"符号分割开,格式如下: array_name=(value1 ... valuen) 使用内置的分割符IF ...

  10. CUDA和cuDNN的安装

    CUDA软件 Windows 打开NVIDIA CUDA网站,选择需要下载的版本,依次选择Windows平台,x86_64架构,10系统,exe(local)本地安装包,再选择Download即可下载 ...