栈和队列总结


一、栈

1.1栈的基本概念

1.1.1栈的定义

栈的逻辑结构是线性结构,是一种受限线性表(受到特定的限制)
栈是只允许在一端进行插入或删除操作线性表,特点是先进后出后进先出(LIFO)。例如撤销的实质就是栈的应用。

1.1.2栈的结构

栈顶允许进行插入删除那一端
栈底不允许进行插入删除的一端

1.1.3出栈顺序的排列组合数问题

n个不同元素进栈,出栈元素不同排列个数为 :
在这里插入图片描述

1.2栈的顺序存储结构

1.2.1顺序栈实现

使用顺序存储的栈称为顺序栈,利用一组地址连续的存储单元存放数据元素

typedef struct{
	Elemtype data[MaxSize];栈元素
	int top; //栈顶指针
	}SqStack;

1.2.2栈顶指针指向不同入栈出栈问题(图示)

栈顶指针:S.top
初始化为-1的情况下,入栈要使top先自加
S.data[++S.top] = x;
出栈时要是top后减
S.data[S.top–] = x

在这里插入图片描述
初始化为0的情况下,刚好与-1时相反
入栈要使top后加
S.data[S.top++] = x;
出栈时要是top先减
S.data[–S.top] = x

在这里插入图片描述

1.2.3栈空、栈满判断(top指向 -1情况)

栈空:S.top == -1;
栈满: S.top == MaxSize - 1;

1.2.4 顺序栈基本操作实现(C++代码)

1.2.4.1初始化
void InitStack(SqStack &s){
	S.top == -1;
}
1.2.4.2判断栈空
bool StackEmpty(SqStack S){
	if(S.top == —1)
		return true;
	else
		return false;
}
1.2.4.3进栈
bool Push(SqStack &S,ElemType X){
	if(S.top == MaxSize - 1)// 判断栈是否已经满
		return false;
	S.data[++S.top] = x ;
	return ture;
1.2.4.4出栈
bool Pop(SqStack &S,ElemType X){
	if(S.top == -1)// 判断栈是否空
		return false;
	x = S.data[S.top--];
	return true;
1.2.4.5读栈顶元素
bool GetTop(SqStack &S,ElemType X){
	if(S.top == -1)// 判断栈是否空
		return false;
	x = S.data[S.top];
	return true;

1.2.5共享栈问题

将两个栈的栈底分别设置在共享空间的两端.
作用:更有效的利用存储空间,减少上溢的可能

在这里插入图片描述
判断左端栈空 top0 = -1,判断右端栈空top1 = MaxSize
判断栈满情况top1 - top0 = 1 (两个栈相邻)

1.3栈的链式存储结构

采用链式存储的栈称为链栈
存储类型课描述为

typedef struct Linknode{
	ElemType data;
	struct Linknode *next;
	} *LiStack;

便于多个栈共享存储空间和提高效率,不存在栈满上溢的情况

1.4 栈错题

一个栈的入栈序列为1,2,3…n,出栈序列是P1,P2,…PN。若p2=3,则P3可能取值的个数是(C)
A. n - 3 B.n - 2 C.n - 1 D.无法确定

分析:4 - n 均为 p3可取的值(例如:4入栈出栈取4,4.5入栈5出栈取5)
讨论1.2,当P1 = 2 时 P3可以取1(1入栈,2入栈出栈,3入栈出栈)
P1 = 1时 P3可以取2(1入栈出栈,2、3入栈,3出栈,2出栈)
最终总数为 N - 1

二、队列

2.1队列的基本概念

2.1.1队列的定义

操作受限的线性表(只允许在表的一端进行插入,在表的另一端进行删除。
其特点是先进先出(FIFO)
队头:允许删除的一端
队尾:允许插入的一端

在这里插入图片描述

2.2队列的顺序存储结构

2.2.1结构描述

typedef struct{
	ElemType data[MaxSize];
	int front,int rear;//队头指针队尾指针
} SqQueue;

在这里插入图片描述
可以利用Q.front == Q.rear == 0 来判断队列是否为空
但不能用Q.rear == MaxSize 作为队列满的条件

2.2.2基本操作

2.2.2.1初始化队列
void InitQueue(SqQueue &Q)
{
	Q.rear = Q.front = 0;
}
2.2.2.2判断队列是否为空
bool QueueEmpty(SqQueue Q)
{
	if(Q.rear == Q.front)
		return true;
	else
		return false;
2.2.2.3入队
bool EnQueue(SqQueue &Q,ElemType x){
	if((Q.rear + 1) % MaxSize == Q.front)
		return false;
	Q.data[Q.rear] = x;
	Q.rear = (Q.rear + 1 )%MaxSize;
	return true;
2.2.2.4出队
bool DeQueue(SqQueue &Q,ElemType &x){
	if(Q.rear == Q.front)
		return false;
	x = Q.data[Q.front];
	Q.front = (Q.front + 1)%MaxSize;
	return true;

2.2.3循环队列的问题

循环队列(逻辑上变成一个循环的队列,但实际上还是顺序存取)里的取余:把无限个正数映射到有限个数字。
其中的 进一操作
队首指针进一 Q.front = (Q.front + 1 ) % MaxSize;
队尾指针进一 Q.rear = (Q.rear + 1 ) % MaxSize;
队列长度 (Q.rear + MaxSize - Q.front)%MaxSize;

2.2.3队列是否满的问题

  1. 牺牲一个单元“队头指针在队尾指针的下一个位置作为队满的标志”
    (Q.rear + 1 ) % MaxSize == Q.front
  2. 设置一个计数器来计数,当Q.size == 0 队空,Q.size == MaxSize 队满
  3. 设置标记位,tag = 0,如果是因为删除导致 Q.front == Q.rear,那么就判断为队空 。tag = 1,如果应为插入导致则为队满 。

2.3队列的链式存储结构

同时带有头指针和尾指针的单链表

typedef struct {
	ElemType data;
	struct LinkNode * next;
	}LinkNode;
typedef struct{
	LinkNode *front,*rear;
}LinkQueue;

2.4链式队列的基本操作

2.4.1初始化

void InitQueue(LinkQueue &Q)
{
	Q.front = Q.rear = (LinkNode*)malloc(sizeof(LinkNode));
	Q.front->next = NULL;
}

2.4.2判断队空

bool IsEmpty(LinkQueue Q)
{
	if(Q.front == Q.rear)
		return true;
	else
		return false;
}

2.4.3入队

void EnQueue(LinkQueue &Q,ElemType x){
	LinkNode *s = (LinkNode *)malloc(sizeof(LinkNode));
	s->data = x;s->next = NULL;
	Q.rear->next = s;
	Q.rear = s;

2.4.4 出队

bool DeQueue(LinkQueue &Q,ElemType &x){
	if(Q.rear == Q.front)
		return false;
	LinkNode *p = Q.front ->next;
	x = p->data;
	Q.front->next = p->next;
	if(Q.rear == p)
		Q.rear = Q.front;
	free(p);
	reutrn true;

2.4 双端队列

允许两端都可以就入队与出队的操作队列
输出受限双端队列:允许一端进行插入和删除,但另一端只能进行插入
输入受限双端队列:允许一端进行插入和删除,但另一端只能进行删除

总结

栈总特点:先进后出
顺序栈,共享栈,链栈他们的特点。
栈的基本操作
队列总特点“先进先出"
指针进一规则,判断队满的三种情况

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值