数据结构(C语言版)第三章栈和队列

目录

3.1 栈和队列的定义和特点

3.1.1栈的定义和特点

3.1.2 队列的定义和特点

3.2 栈的表示和操作的实现

 3.2.1栈的类型定义

3.2.2  顺序栈的表示和实现

顺序栈的存储结构定义:

初始化:

入栈:

出栈:

取栈顶元素:

遍历栈中元素:

获取栈中元素个数:

判断栈是否为空:

3.2.3 链栈的表示和实现

链栈的存储结构定义:

初始化:

入栈:

出栈:

取栈顶元素:

遍历栈中元素:

获取栈中元素个数:

判断链栈是否为空:

3.2.4 栈的应用----括号的匹配检测

3.2.5 栈的相关考研真题:

3.3 队列的表示和操作的实现

3.3.1 队列的类型定义

3.3.2 循环队列----队列的顺序表示和实现

队列的存储结构:

初始化:

入队:

出队:

取队头元素:

求循环队列的长度:

判断队列是否为空:

遍历队列中元素:

3.3.3 队列的相关考研真题


数据结构(C语言版)第三章栈和队列_第1张图片

3.1 栈和队列的定义和特点

3.1.1栈的定义和特点

栈是限定仅在表尾进行插入或删除的线性表。因此,对栈来说,表尾端有特殊含义,称为栈顶,相应地,表头端称为栈底。不含元素的空表称为空栈


栈又称为后进先出的线性表,形象地看成是一个无盖的铁桶,大家脑补一下。

3.1.2 队列的定义和特点

 队列是一种先进先出的线性表,它只允许在表的一端进行插入,而在另一端删除元素,大家可以想象一下我们生活中的排队。


在队列中,允许插入的一端称为队尾,允许删除的一端称为队头

3.2 栈的表示和操作的实现

 3.2.1栈的类型定义

1.InitStack(&S)  构造一个空栈S


2.Push(&S,e)  元素入栈操作


3. Pop(&S,&e)  元素出栈操作


4.GetTop(S)  取栈顶元素


5.StackLength(S)  统计栈中元素的个数


6.StackTraverse(S)  遍历栈中元素


7.StackEmpty(S)  判断栈是否为空

3.2.2  顺序栈的表示和实现

 顺序栈是利用顺序存储结构实现的栈,即利用一组地址连的存储单元依次存放自栈底到栈顶的数据元素。

顺序栈的存储结构定义:

typedef struct{
	SElemType *top,*base;//定义栈顶和栈底指针
	int stacksize;//定义栈的容量
}SqStack;

初始化:

Status InitStack(SqStack &S){//初始化一个空栈
	S.base=new SElemType[MAXSIZE];//为顺序栈动态分配一个最大容量为MAXSIZE的空间
	if(S.base==NULL) return ERROR;//判断存储是否分配成功
	S.top=S.base;//将top初始化为base,置为空栈
	S.stacksize=MAXSIZE;//stacksize置为最大容量MAXSIZE
	return OK;
}

入栈:

Status Push(SqStack &S,SElemType e){//入栈
	if(S.top-S.base==S.stacksize) return ERROR;//判断是否栈满
	*S.top=e;
	S.top++;
	return OK;
}

出栈:

Status Pop(SqStack &S,SElemType &e){//出栈
	if(S.top==S.base) return ERROR;//判断栈是否为空
	S.top--;
	e=*S.top;
	return OK;
}

取栈顶元素:

SElemType GetTop(SqStack S){//获取栈顶元素
    if(S.top!=S.base)
        return *(S.top-1);
}

遍历栈中元素:

Status PrintfStack(SqStack S){//遍历栈内的所有元素
	SElemType *p;
	p=S.base;
	printf("栈中的元素为:");
	while(p!=S.top){
		printf("%d ",*p);
		p++;
	}
	printf("\n");
}

获取栈中元素个数:

int StackLength(SqStack S){//获取栈的长度
	int len=0;
	SElemType *s;
	s=S.base;
	while(s!=S.top){
		len++;
        s++;
	}
	printf("栈的长度为:%d\n",len);
}

判断栈是否为空:

Status StackEmpty(SqStack S){//判断栈是否为空
	if(S.top==S.base) return ERROR;
	else
	return OK;
}

3.2.3 链栈的表示和实现

链栈的存储结构定义:

typedef struct StackNode
{
	SElemType data;
	struct StackNode *next;
}StackNode,*LinkStack;

初始化:

Status InitStack(LinkStack &S){//链式栈的初始化
	S=NULL;
	return OK;
}

入栈:

Status Push(LinkStack &S,SElemType e){//元素入栈
	StackNode *p;
	p=new StackNode;
	p->data=e;
	p->next=S;
	S=p;
	return OK;
}

出栈:

Status Pop(LinkStack &S,SElemType &e){//元素出栈
	if(S==NULL) return ERROR;
	e=S->data;
	StackNode *p;
	p=S;
	S=S->next;
	delete p;
	return OK;
}

取栈顶元素:

Status GetTop(LinkStack S){//获取栈顶元素
	if(S!=NULL) return S->data;
}

遍历栈中元素:

Status printfStack(LinkStack S){//遍历链式栈中的元素
	StackNode *p;
	p=S;
	printf("链式栈中的元素为:");
	while(p!=NULL){
		printf("%d ",p->data);
		p=p->next;
	}
	printf("\n");
}

获取栈中元素个数:

int StackLength(LinkStack S){//获取栈的长度
	StackNode *p;
	p=S;
	int count=0;
	while(p!=NULL){
		count++;
		p=p->next;
	}
	printf("栈的长度为:%d\n",count);
}

判断链栈是否为空:

Status StackEmpty(LinkStack S){//判断链式栈是否为空
	if(S==NULL) return ERROR;
	return OK;
}

3.2.4 栈的应用----括号的匹配检测

案例:

[[]](){}  匹配

[[]](}   不匹配

直接上代码: (此案例只适用于[],(),{}三种括号,如要增加其余括号,在程序中修改即可)

#include
#include
using namespace std;
typedef struct
{
	char *base;//定义栈底指针
	char *top;//定义栈顶指针
	int stacksize;
}SqStack;
int InitStack(SqStack &S)//初始化
{
	S.base=new char[100];
	if(S.base==NULL) return 0;
	S.top=S.base;//此处很重要,位置不能互换
	S.stacksize=100;
	return 1;
}
int Push(SqStack &S,char e)//入栈
{
	if(S.top-S.base==S.stacksize) return 0;
	*S.top++=e;
	return 1;
}
int Pop(SqStack &S,char &e)//出栈
{
	if(S.base==S.top) return 0;
	e=*--S.top;
	return 1;
}
char GetTop(SqStack S)//取栈顶元素
{
	if(S.base!=S.top)
	return *(S.top-1);
}
int Match(SqStack &S,char str[])
{
	int flag=1;
	int len=strlen(str);
	for(int i=0;i

案例测试:

测试案例一:

[[]](){}

运行结果:

数据结构(C语言版)第三章栈和队列_第2张图片


测试案例二:

[[]](}

运行结果:

数据结构(C语言版)第三章栈和队列_第3张图片

3.2.5 栈的相关考研真题

1.给定有限符号集S,in和out均为S中所有元素的任意排列。对于初始为空的栈ST,下
列叙述中,正确的是(  ) 。   【全国联考2022年】
A若i是ST的人栈序列,则不能判断out是否为其可能的出栈序列
B若out是ST的出栈序列,则不能判断in是否为其可能的入栈序列
C.若in是ST的入栈序列,out是对应in的出栈序列,则i与out一定不同
D.若in是ST的入栈序列,out 是对应in的出栈序列,则in与out可能互为倒序


答案:D

解析:根据栈的特性可以根据入栈序列,可以推出可能的出栈序列。同样,根据出栈序列,可以推出可能的入栈序列。若元素进栈即出栈,则入栈序列和出栈序列相同。若元素依次进栈完后,再依次出栈,则入栈序列和出栈序列互为倒序。由此,A,B,C错误,D选项正确。


2.对空栈S进行Push和Pop操作,人栈序列为a,b,c,d,e,经过Push,Push,Pop,Push Pop,Push,Push,Pop操作后,得到的出栈序列是(  )。 【全国联考2020年】

A.b,a,c              B.b,a,e           C.b,c,a            D.b,c,e


答案:D
解析:栈是一种后进先出的数据结构,Push 和Pop操作分别为入栈和出栈操作。如题所述的操作过程:a入栈,b入栈,b出栈,c人栈,c出栈,d入栈,e入栈,e出栈。因此,得到的出栈序列是b,c,e。


3.若栈S中保存整数,栈S2中保存运算符,函数F()依次执行下述各步操作:
(1)从S1中依次弹出两个操作数a和b
(2)从S2中弹出一个运算符op

(3)执行相应的运算b op a

(4)将运算结果压入S1中
假定S1中的操作数依次是5,8,3,2(2在栈顶),S2中的运算符依次是*,-,+(+在栈顶)。
调用3次F()后,S1栈顶保存的值是(  )。 【全国联考2018年】
A.-15         B.15        C.-20         D.20


答案:B
解析:第一次调用F():2和3依次出栈,+出栈,a=2,b=3,op=+,b op a=3+2=5,将5压
入S1中。
第二次调用F():5和8依次出栈,-出栈,a=5,b=8,op=-,b op a=8-5=3,将3压入
S1中。
第三次调用F():3和5依次出栈,*出栈,a=3,b=5,op=*,b op a=5*3=15,将15压入
S1中。
综上所述,调用3次F()后,S栈顶保存的值是15。


4.下列关于栈的叙述中,错误的是(  )。【全国联考2017】
I.采用非递归方式重写递归程序时必须使用栈

Ⅱ.函数调用时,系统要用栈保存必要的信息

Ⅲ只要确定了入栈次序,即可确定出栈次序
Ⅳ栈是一种受限的线性表,允许在其两端进行操作
A.仅I          B.仅I、Ⅱ、Ⅲ       C.仅I、Ⅲ、Ⅳ      D.仅Ⅱ,Ⅲ,Ⅳ


答案:C
解析:采用非递归方式重写递归程序时,不一定使用栈,如计算斐波那契数列迭代实现只需要一个循环即可;确定了入栈次序也无法确定出栈次序,因为出栈的时机无法确定;栈是一一种受限的线性表,只允许在其一端进行操作。(栈顶进行操作)

3.3 队列的表示和操作的实现

3.3.1 队列的类型定义

1.InitQuese(&Q)  构造一个空的队列


2. EnQuese(&Q)  元素入队


3. DeQuese(&Q,&e)  元素出队


4.GetHead(Q)  取队头元素


5.QueseLength(Q)  求循环队列的长度


6.QueseEmpty(Q) 判断队列是否为空


7.QueseTraverse(Q)  遍历队列中的元素

3.3.2 循环队列----队列的顺序表示和实现

队列的存储结构:

typedef struct{
	QElemType *base;//存储空间的基地址
	int front;//头指针
	int rear;//尾指针
}SqQuese;

初始化:

Status InitQuese(SqQuese &Q){//队列的初始化
	Q.base=new QElemType[MAXQSIZE];//为队列分配一个最大容量MAXSIZE的存储空间
	if(Q.base==NULL) return ERROR;
	Q.front=Q.rear=0;//将队列的头指针和尾指针置为0,队列为空
	return OK;
}

入队:

Status EnQuese(SqQuese &Q,QElemType e){//入队
	if((Q.rear+1)%MAXQSIZE==Q.front) return ERROR;//判断队列是否满
	Q.base[Q.rear]=e;入队,新元素插入队尾
	Q.rear=(Q.rear+1)%MAXQSIZE;//队尾指针加1
	return OK;
}

出队:

Status DeQuese(SqQuese &Q,QElemType &e){//出队
	if(Q.rear==Q.front) return ERROR;//判断队列是否为空
	e=Q.base[Q.front];//保存队头元素
	Q.front=(Q.front+1)%MAXQSIZE;//队头指针加1
	return OK;
}

取队头元素:

QElemType GetHerd(SqQuese Q){//获取队头元素
	if(Q.front==Q.rear) return ERROR;//判断队列是否为空
	return Q.base[Q.front];//返回队头元素
}

求循环队列的长度:

QElemType GetHerd(SqQuese Q){//获取队头元素
	if(Q.front==Q.rear) return ERROR;
	return Q.base[Q.front];
}

判断队列是否为空:

Status QueseEmpty(SqQuese Q){//判断队是否为空
	if(Q.front==Q.rear) return ERROR;
	return OK;
}

遍历队列中元素:

Status QueseTraverse(SqQuese Q){//遍历队列中的所有元素
	if(Q.front==Q.rear) printf("队列为空!\n");
	else{
		printf("队的元素为:");
	while(Q.front!=Q.rear){
		printf("%d ",Q.base[Q.front]);
		Q.front++;
	}
	printf("\n");
	}
}

3.3.3 队列的相关考研真题

1.已知初始为空的队列Q的一端仅能进行入队操作,另外一端既能进行入队操作又能进行出队操作。若Q的入队序列是1,2,3,4,5,则不能得到的出队序列是(    )。  【全国联考2021】

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


答案:D

解析:这个队列两边都可以进行出队,但只有一端能够进行入队,并且入队的序列已经告诉我们了,按照要求,只有D不符合入队要求,无法得到对应的出队序列。


2.循环队列存放在一维数组A[0…M-L1中,end1指向队头元素,end2指向队尾元素的后一个位置。假设队列两端均可进行入队和出队操作,队列中最多能容纳M-1个元素,初始时为空。下列判断队空和队满的条件中,正确的是(   )。【全国联考2014年】
A.队空:end1==end2       队满:endl==(end2+1)  mod  M
B.队空:endl==end2        队满:end2==(end1+1) mod(M-1)
C.队空:end2==(end1+1) mod M     队满:endl==(end2+1) mod M
D.队空:endl==(end2+1) mod M      队满:end2==(end1+1) mod (M-1)


答案:A

解析:按照队列的相关操作只有A选项符合题意。

分享

我今天刷到了一个关于丘吉尔的电影中的演讲片段,很振奋人心,在面对德军的入侵,这位刚刚上任了20天的首相用一段激情四射的演讲打动了所有人的内心,有一句话很好,在这里分享给大家,“成功不是终点,失败也并非末日,最重要的是继续前进的勇气。”,请大家记住这位优秀的首相------温斯顿.丘吉尔。共勉!!!

你可能感兴趣的:(数据结构,数据结构)