C语言示例代码讲解栈与队列

目录
    • 栈的定义
  • 顺序栈
    • 顺序栈的定义
    • 顺序栈的初始化
    • 顺序栈的入栈
    • 顺序栈的出栈
    • 取顺序栈的栈顶元素
  • 链栈
  • 队列
    • 队列的定义
  • 队列的顺序表达与实现
    • 队列顺序存储结构
    • 假溢出
  • 循环队列
    • 循环队列的初始化
    • 循环队列的入队
    • 循环队列的出队
  • 链队列
    • 链栈的初始化
    • 链栈的入队
    • 链栈的出队

上文详细的讲解了顺序表与链表的实现,相信大家在顺序表与链表的指基础上,很容易就能学会站和队列,废话不多说,我们马上开始!

栈的定义

栈是一种线性表,但限定这种线性表只能在某一端进行插入和删除操作

假设栈 【s = (a1,a2,……,an) 】,a1为栈底元素,an为栈顶元素。由于栈只能在栈顶进行插入和删除操作,所以进栈次序依次为【a1,a2,……,an】,出栈次序为【an,……,a2,a1】

由此可见:栈的操作特性可以明显地概括为后进先出

栈类似于线性表,它也有两种对应的存储方式分别为顺序栈和链栈。

顺序栈

顺序栈的定义

Q:什么是顺序栈?

A:采用顺序存储的栈成为顺序栈。它利用一组地址连续的存储单位存放自栈底到栈顶的数据元素,同时附设一个指针(top)来指示当前栈顶的位置。

栈的顺序存储类型可描述为

#define MaxSize 100				//定义栈中元素的最大个数
typedef struct
{
	SElemtype *base;			//栈底指针
	SElemtype *top;				//栈顶指针
	int stacksize				//栈可用的最大容量
}SqStack; 

顺序栈的初始化

Q:什么是顺序栈的初始化?

A:顺序栈的初始化操作就是为顺序栈动态分配一个最大容量为 MaxSize 的数组空间。

实现原理

  1. 为顺序栈动态分配一个最大容量为MAXSIZE的数组
  2. 栈顶指针top初始为base,表示栈为空
  3. stacksize置为栈的最大容量MaxSize

代码演示

Status InitStack(SqStack &S)
{//构造一个空栈S
	S. base=new SElemType[MaxSize];		//为顺序栈动态分配一个最大容量为MAxsini
	if(!S. base) exit(OVERFLOW);		//存储分配失败
	S. top=S. base;						//top初始为base,空栈
	S. stacksize=MaxSize;				//stacksize置为栈的最大容量MaxSize
	return OK;
}

顺序栈的入栈

Q:什么是顺序栈的入栈?

A:入栈操作是将新元素进入栈

实现原理

  1. 判断栈是否满了,若满了返回ERROR
  2. 将新元素压入栈,栈顶指针加1

代码演示

Status Push(SqStack	&S,SElemType e)
{//插入元素e为新的栈顶元素
	if(S.top-S.base==S:stacksize) return ERROR;//栈满
	*S. top++=e;							   //元素e压入栈顶,栈顶指针加1
	return OK;
}

顺序栈的出栈

Q:什么是顺序栈的出栈?

A:出栈操作是将栈顶元素删除

实现原理

  1. 判断栈是否空,若空则返回ERROR
  2. 栈顶指针减1,栈顶元素出栈

代码演示

Status Pop(SqStack &S,SElemType &e)
(//删除S的栈顶元素,用e返回其值
	if(S.top==S.base) return ERROR;//栈顶
	指针减1,将栈顶元素赋给e	   //栈顶指针减1,将栈顶元素赋给e
	e=*--S.top;
	return OK;
)

取顺序栈的栈顶元素

Q:如何取顺序栈的栈顶元素?

A:当栈非空时,此操作返回当前栈顶元素的值,栈顶指针保持不变。

实现原理

  1. 判断栈是否空
  2. 返回栈顶元素的值,栈顶指针不变

代码演示

SElemType GetTop (SqStack S)
{//返回s的栈顶元素,不修改栈顶指针
	if(S.top!=S.base) 		        //栈非空
	    return*(S.top-1);			//返回栈顶元素的值,栈顶指针不变
)

链栈

采用链式存储的栈称为链栈。链栈的优点是便于多个栈共享存储空间和提高其效率,且不存在栈满上溢的情况。通常采用单链表实现。

栈的顺序存储类型可描述为

typedef struct Linknode
{
	ElemType data;				//数据域
	struct Linknode *next;		//指针域
} *LiStack; 

采用链式存储,便于结点的插入与删除。链栈的操作与链表类似,入栈和出栈的操作都在链表的表头进行。

队列

队列的定义

队列是一种线性表,但限定这种线性表只能在表的一端进行插入,在另一端进行删除。允许删除的一端为队头,又称为队首,允许插入的一端为队尾

队列与生活中的排队一样,最早排队的最先离开,队列的操作特性可以明显地概括为先进先出

队列有两种存储表示,分别为顺序表示与链式表示

队列的顺序表达与实现

队列顺序存储结构

和顺序栈相类似,在队列的顺序存储结构中,除了用一组地址连续的存储单元依次列头到队列尾的元素之外。还需附设两个整型变量【front】和【rear】分别指示队列头元素及队间的位置(后面分别称为头指针和尾指针)。

队列的顺序存储结构表示如下:

#define   MAXSIZE    100		//队列容量
typedef   struct
{
	ElemType *base;             //存储空间
	int front,rear;            	//队首,队尾
}SqQueue ;

假溢出

图(1)所示为队列的初始状况。此时有【front == rear == 0】 成立。该条件可以作为队列判空的条件。

但是【rear == MAXSIZE】不能作为队列满的条件。为什么呢?

图(4)队列中只有一个元素,仍满足该条件。这时入队出现上溢出。但是这种溢出并不是真正的溢出,在队列中依然存在可以存放元素的空位置,所以是一种假溢出。

如何解决循环链表的这一缺点呢? ​

循环队列

Q:什么是循环队列?

A:将顺序队列臆造成一个环状的空间,即把存储队列元素的表从逻辑上视为一个环,称为循环队列。

循环队列的初始化

Q:什么是循环队列的初始化?

A:循环队列的初始化就是动态分配一个预定义大小为 MAXSIZE 的数组空间

实现原理

  1. 为队列动态分配一个最大容量为MAXSIZE的数组空间
  2. base指向数组空间的首地址
  3. 头指针与尾指针置为零,表示队列为空

代码演示

Status InitQueue ( SqQueue  &Q )
{
	Q.base=new  ElemType[MAXSIZE];
	if(!Q.base)	return OVERFLOW;
	Q.front=Q.rear=0;
	return OK;
} 

循环队列的入队

Q:什么是循环队列的入队?

A:入队操作是指在队尾插入一个新的元素

实现原理

  1. 判断队列是否满
  2. 满了返回ERROR
  3. 将新元素插入队尾
  4. 队尾指针加一

代码演示

Status EnQueue(SqQueue &Q,ElemType e)
{
    if((Q.rear+1)%MAXSIZE==Q.front)	//判满
	    return ERROR;
	Q.base[Q.rear]=e;
	Q.rear=(Q.rear+1)%MAXSIZE;
	return OK;
}

循环队列的出队

Q:什么是循环队列的出队?

A:出队操作是删除队头元素

实现原理

  1. 判断队列是否为空
  2. 为空返回ERROR
  3. 保留队头元素
  4. 队头指针加一

代码演示

Status DeQueue(SqQueue &Q, ElemType &e)
{
    if( Q.rear==Q.front )
		return ERROR;			//判空
	e = Q.base[Q.front];
	Q.front = (Q.front+1)%MAXSIZE;
	return OK;
}

链队列

Q:什么是链队列?

A:队列的链式表示称为链队列。它实际上是一个同时带有队头指针和队尾指针的单链表,头指针指向对头结点,尾指针指向队尾结点。

队列的链式存储如图:

队列的链式存储类型可描述为:

typedef struct Qnode
{
	ElemType data;
    struct QNode * next;
}Qnode,*QueuePtr;                  //结点
typedef struct
{
	QueuePtr  front;
	QueuePtr rear;
}LinkQueue;                       //链队  

链栈的初始化

Q:什么是链队列的初始化?

A:链栈的初始化操作就是构建一个只有头结点的空队。

实现原理

  1. 生成新结点作为头结点
  2. 队头指针和队尾指针指向该结点
  3. 头指针的指针域置空

代码演示

Status InitQueue(LinkQueue &Q)
{
	Q.front=Q.rear=new QNode;
	p->next=NULL;
	return OK;
} 

链栈的入队

实现原理

  1. 为入队元素分配结点空间,用指针p指向
  2. 将新结点数据域置为e
  3. 将新结点插入到队尾
  4. 修改队尾指针为p

代码演示

Status EnQueue(LinkQueue &Q,ElemType e)
{
	p=new QNode;		//为入队元素分配结点空间,用指针p指向
	p->data=e;	        //将新结点数据域置为e
	p->next=NULL;
	Q.rear->next=p;     //将新结点插入到队尾
	Q.rear=p;			//修改队尾指针为p
	return OK;
}

链栈的出队

实现原理

  1. 判断是否为空,为空返回ERROR
  2. 保留头元素空间,以备释放
  3. 修改头指针的指针域,指向下一结点
  4. 判断出队元素是否是最后一个元素,若是,将队尾指针重新赋值,指向头结点
  5. 释放原队头元素的空间

代码演示

Status DeQueue(LinkQueue &Q,ElemType &e)
{
	if(Q.front==Q.rear)			//若队列为空,返回ERROR
		return ERROR;
	QNode *p=Q.front->next;		//保留头元素空间,以备释放
	Q.front->next=p->next;		//修改头指针的指针域,指向下一结点
    if(Q.rear==p)				//判断出队元素是否是最后一个元素,若是,将队尾指针重新赋值,指向头结点
		Q.rear=Q.front;
	delete p;					//释放原队头元素的空间
	return OK;
}

到此这篇关于C语言示例代码讲解栈与队列的文章就介绍到这了,更多相关C语言栈与队列内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C语言中用栈+队列实现队列中的元素逆置

    下面举例代码: 提到的Q是一个队列,S是一个空栈,实现将队列中的元素逆置的算法 #include<stdio.h> #define MaxSize 10 typedef int ElemType; typedef struct{     ElemType data[MaxSize];     int front,rear; }Queue; typedef struct{     ElemType data[MaxSize];     int top; }SqStack;   void Init

  • C语言用栈模拟实现队列问题详解

    目录 题目描述 题目链接 思路分析 代码实现 题目描述 请你仅使用两个栈实现先入先出队列.队列应当支持一般队列支持的所有操作(push.pop.peek.empty). 你只能使用标准的栈操作 —— 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的. 题目链接 用栈实现队列 思路分析 题目的意思是要用两个栈来模拟实现一个队列.仅可以用栈的基本功能实现队列的基本功能.所以需要创建两个栈.所以这两个栈st1,st2可用一个结构

  • C语言栈与队列面试题详解

    目录 1.括号匹配问题 2.用队列实现栈 3.用栈实现队列 4.设计循环队列 1.括号匹配问题 链接直达: 有效的括号 题目: 思路: 做题前,得先明确解题方案是啥,此题用栈的思想去解决是较为方便的,栈明确指出后进先出.我们可以这样设定: 遇到左括号“ ( ”.“ [ ”.“ { ”,入栈. 遇到右括号“ ) ”.“ ] ”.“ } ”,出栈,跟左括号进行匹配,不匹配就报错. 上两句话的意思就是说我去遍历字符串,如果遇到左括号,就入栈:遇到右括号,就出栈顶元素,并判断这个右括号是否与栈顶括号相匹

  • C语言超详细讲解栈与队列实现实例

    目录 1.思考-1 2.栈基本操作的实现 2.1 初始化栈 2.2 入栈 2.3 出栈 2.4 获取栈顶数据 2.5 获取栈中有效元素个数 2.6 判断栈是否为空 2.7 销毁栈 3.测试 3.1测试 3.2测试结果 4.思考-2 5.队列的基本操作实现 5.1 初始化队列 5.2 队尾入队列 5.3 队头出队列 5.4 队列中有效元素的个数 5.5 判断队列是否为空 5.6 获取队头数据 5.7 获取队尾的数据 5.8 销毁队列 6.测试 6.1测试 6.2 测试结果 1.思考-1 为什么栈用

  • C语言 浅谈栈与队列的定义与操作

    目录 栈的定义 栈的实现 前置 初始化栈 栈的销毁 栈的插入 出栈的操作 取栈顶元素 栈的大小 队列的定义 队列的基本操作 队列的初始化 队列的销毁 队列的插入 队列的删除 队列的判空 取出队头元素 取出队尾元素 队列的大小 栈的定义 栈同样是一种线性表,它的特性是插入元素必须从后面插入,删除元素也是从后面删除,进行数据删除和插入的一端称为栈顶,另一端是栈底. 压栈-就是插入元素 出栈-就是删除元素 它可以用数组实现也可以用链表实现 但是用数组实现更好,因为链表的插入和删除要进行遍历,而数组可以

  • C语言数据结构进阶之栈和队列的实现

    目录 栈的实现: 一.栈的概念和性质 二.栈的实现思路 三.栈的相关变量内存布局图 四.栈的初始化和销毁 五.栈的接口实现: 1.入栈 2.出栈 3.获取栈顶的数据 4.获取栈的元素个数 5.判断栈是否为空 队列的实现: 一.队列的概念和性质 二.队列的实现思路 三.队列相关变量的内存布局图 四.队列的初始化和销毁 五.队列的接口实现: 1. 入数据 2.出数据 3.取队头数据 4.取队尾数据 5.获取队列元素个数 6.判断队列是否为空 总结 栈的实现: 一.栈的概念和性质 栈(stack)又名

  • C语言分别实现栈和队列详解流程

    目录 什么是栈 栈的结构图示 栈的实现 创建栈的结构体 初始化栈 入栈 出栈 获取栈顶元素 获取栈中有效元素个数 检测栈是否为空 栈的销毁 什么是队列? 队列的实现 创建队列结构体 初始化队列 队尾入队列 队头出队列 获取队列头部元素 获取队列尾部元素 获取队列中元素个数 检测队列是否为空 销毁队列 什么是栈 栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素的操作.进行数据插入和删除的一端称为栈顶,另一端称为栈底.栈中的数据元素遵守先进后出LIFO(Last In First Out

  • C语言栈与队列相互实现详解

    目录 一.本章重点 二.队列实现栈 三.栈实现队列 四.解题思路总结 一.本章重点 用两个队列实现栈 用两个栈实现队列 解题思路总结 二.队列实现栈 我们有两个队列: 入栈数据1. 2. 3 可以将数据入队列至队列一或者队列二. 如何出栈? 但出栈要先出1,怎么办? 第一步: 将队列一出队n-1个至队列二. 第二步: pop队列一的最后一个元素. 接下来怎么入栈呢? 将元素入队至不为空的队列. 怎么判断栈空? 队列一和队列二都为空的情况下,栈就是空的. 如何取栈顶元素? 取不为空的队列尾部元素.

  • C语言循环队列与用队列实现栈问题解析

    目录 “莫听穿林打叶声,何妨吟啸且徐行” 这里是目录 循环队列题目描述题目链接思路分析代码实现 用队列实现栈题目描述题目链接思路分析代码实现 循环队列 循环队列: 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环循环队列的好处:可以重新利用队列的空间.我们可以利用这个队列之前用过的空间.在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间.但是使用循环队列,我们能使用这些空间去存储新的值. 题目描述 设计你

  • C语言示例代码讲解栈与队列

    目录 栈 栈的定义 顺序栈 顺序栈的定义 顺序栈的初始化 顺序栈的入栈 顺序栈的出栈 取顺序栈的栈顶元素 链栈 队列 队列的定义 队列的顺序表达与实现 队列顺序存储结构 假溢出 循环队列 循环队列的初始化 循环队列的入队 循环队列的出队 链队列 链栈的初始化 链栈的入队 链栈的出队 上文详细的讲解了顺序表与链表的实现,相信大家在顺序表与链表的指基础上,很容易就能学会站和队列,废话不多说,我们马上开始! 栈 栈的定义 栈是一种线性表,但限定这种线性表只能在某一端进行插入和删除操作 假设栈 [s =

  • C语言超详细讲解栈的实现及代码

    目录 前言 栈的概念 栈的结构 栈的实现 创建栈结构 初始化栈 销毁栈 入栈 出栈 获取栈顶元素 获取栈中有效元素个数 检测栈是否为空 总代码 Stack.h 文件 Stack.c 文件 Test.c 文件 前言 栈的概念 栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作.进行数据插入和删除操作的一端称为栈顶,另一端称为栈底.栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则.有点类似于手枪弹夹,后压进去的子弹总是最先打出,除非枪坏了. 压栈:栈的插入

  • C语言编程数据结构的栈和队列

    目录 栈 数组实现 标题全部代码 Stack_array.c Stack_array.h 初始化数组栈 满栈后扩容 是否为空栈 压栈和退栈 链表实现 stack_chain.h stack_chain.c 整个压栈流程 整个弹栈流程 出栈情况 队列 队列的实现 queue_chain.h queue_chain.c 一个结构体类型用于维护这个队列 概念流程图 入队列的实现 出队列的实现 是否空队 栈 栈是一种以后进先出为顺序对对象进行添加或删除的数据结构 对栈进行形象记忆就像是桌子上的一堆书或一

  • Scala文件操作示例代码讲解

    目录 1. 读取数据 1.1 按行读取 1.2 按字符读取 Scala使用source.buffered方法按字符读取文件 一个示例 1.3 读取词法单元和数字 1.4 从URL或者其他源读取数据 1.5 读取二进制文件 2. 写入文件 2.1 使用java.io.PrintWriter类 2.2 使用java.io.FileWriter类 2.3 使用java.io.FileOutputStream类 2.4 几种写入的区别 2.5 使用第三方库 3. Scala序列化和反序列化 3.1 什么

  • C语言基于考研的栈和队列

    目录 栈 栈的基本操作 三角矩阵 总结 栈 栈的基本操作 InitStack(&S):初始化 StackEmpty(S):判空,空则true,非空则false Push(&S,x):入栈 Pop(&S,&x):出栈,并用x返回元素内容 GetTop(S,&x):读栈顶元素 DestroyStack(&S):销毁并释放空间 栈是一种受限的线性表,只允许在一端操作 栈若只能在栈顶操作,则只可能上溢 采用非递归方式重写递归时,不一定要用栈,比如菲波那切数列只要用循

  • js 判断浏览器使用的语言示例代码

    复制代码 代码如下: <script type="text/javascript"> var language = navigator.browserLanguage?navigator.browserLanguage:navigator.language; alert(language); if (language.indexOf('en') > -1) document.location.href = 'english.htm'; else if (languag

  • SpringBoot整合Liquibase的示例代码

    目录 整合1 整合2 SpringBoot整合Liquibase虽然不难但坑还是有一点的,主要集中在配置路径相关的地方,在此记录一下整合的步骤,方便以后自己再做整合时少走弯路,当然也希望能帮到大家~ 整合有两种情况 在启动项目时自动执行脚本,若新添加了Liquibase脚本需要重启项目才能执行脚本 在不启动项目时也能通过插件或指令手动让它执行脚本 整合要么只整合1,要么1.2一起整合 只整合2不整合1的话,项目启动时会生成liquibase相关的bean时报错 整合1 引入Maven依赖 这里导

  • C语言编程数据结构栈与队列的全面讲解示例教程

    目录 一.栈的表示和实现 1栈的概念和结构 2栈的初始化 3压栈(栈顶插入一个数据) 4出栈(栈顶删除一个数据) 5取栈顶元素 6取栈顶元素 7判断栈是否为空 二.队列的表示和实现 1队列的概念及结构 2队列的实现 3队列初始化 4入队(队尾插入一个数据) 5出队(队头删除一个数据) 6取队头数据 7取队尾数据 8计算队列中数据个数 9判断队列是否为空 10销毁队列 总结 一.栈的表示和实现 1栈的概念和结构 栈:一种特殊的线性表(逻辑上数据是连着放的),其只允许在固定的一端进行插入和删除操作.

随机推荐