004栈和对列(完)

  1. 栈: 限定仅在表尾进行插入和删除操作的线性表。
  2. 栈被称为先进后出的线性表
  3. 允许进行插入和删除操作的一端称为栈顶,另一端称为栈底
  4. 空栈: 不含任何元素的栈

在这里插入图片描述

抽象数据类型

在这里插入图片描述

顺序栈

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

在这里插入图片描述

  • 插入元素
Status Push(SqStack * S, SElemType e)
{
	if(S->top == MAXSIZE - 1)  /* 栈已满 */
		return ERROR;
	S->data[++S->top] = e;
	return OK;
}
  • 删除元素
Status Pop(SqStack * S, SElemType * e)
{
	if(S->top == -1)  /* 栈为空 */
		return ERROR;
	*e = S->data[top--];
	return OK;	
}

两栈共享空间

  • 基本思路:
  1. 数组有两个端点,两个栈有两个栈底
  2. 让一个栈的栈底为数组的始端,即下标为0处,另一个栈底为数组的末端,即下标为数组长度n-1处。
  3. 两个栈如果增加元素就是两端点向中间延伸
  4. 当两个栈都是空栈,栈1的top为-1,栈2的top为n
  5. 数组插满的判断条件:top1+1==top2
  • 适用场景:

通常用于两个栈的空间需求具有相反关系:一个栈在增长,连一个栈在缩短

在这里插入图片描述

/* 两站共享空间结构 */ 
typedef struct 
{
	SElemType data[MAXSIZE];
	int top1;   /* 栈1的栈顶指针 */
	int top2;   /* 栈2的栈顶指针 */
}SqDoubleStack;
  • 插入元素
Status Push(SqDoubleStack *S, SElemType e, int stackNumber)
{
	if(S->top1 + 1 == S->top2)  /* 两栈共享数组已被插满 */
		return ERROR;   
	if(stackNumber == 1)
		S->data[++S->top1] = e;
	else
		S->data[--S->top2] = e;
	return OK;
}
  • 删除元素:
Status Pop(SqDoubleStack *S, SElemType * e, int stackNumber)
{
	if(stackNumber == 1)
	{
		if(S->top1 == -1)
			return ERROR;
		*e = S->data[top1--];
	}
	else
	{
		if(S->top2 == MAXSIZE)
			return ERROR;
		*e = S->data[top2++];
	}
	return OK;
}

链栈

  1. 栈顶放在单链表的头部,在链栈中不需要头结点。
  2. 空链栈:top=NULL时,为空链栈

在这里插入图片描述

typedef struct StackNode
{
	SElemType data;
	struct StackNode * next;
}StackNode, * LinkStackPtr;
typedef struct LinkStack
{
	LinkStackPtr top;
	int count;
}LinkStack;
  • 入栈操作:
    在这里插入图片描述
Status Push(LinkStack * S, SElemType e)
{
	LinkStackPtr s = (LinkStackPtr)malloc(sizeof(StackNode));
	s->data = e;
	s->next = S->top;
	S->top = s;
	count++;
	return OK;
}
  • 出栈操作:
    在这里插入图片描述
Status Pop(LinkStack *S, SElemType *e)  
{
	LinkStackPtr p;
	if(StackEmpty(*S))
		return ERROR;
	*e = S->top->data;
	p = S->top;
	S->top = S->top->next;
	free(p);
	S->count--;
	return OK;
}

队列

  • 定义:

只允许在一端进行插入操作,而在另一端进行删除操作的线性表。

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

在这里插入图片描述

抽象数据类型

在这里插入图片描述

顺序存储结构

简单顺序存储

  • 队列顺序存储的不足:
  1. 入列时时间的复杂度为O(1)

在这里插入图片描述

  1. 出栈时时间的复杂度为O(n)(复杂度较高):

在这里插入图片描述

  1. front指针: 指向队列的队头元素。
  2. rear指针: 指向队尾元素的下一个位置。

循环对列

  • 定义:

对列的头尾相连接的顺序存储结构。

  • 存储结构:
typedef int QElemType;
typedef struct
{
	QElemType data[MAXSIZE];
	int front;  /* 头指针 */
	int rear;  /* 尾指针 */
}SqQueue;
  • 初始化:
Status InitQueue(SqQueue * Q)
{
	Q->front = 0;
	Q->rear = 0;
	return OK;
}
  • 入队操作:
Status EnQueue(SqQueue * Q, QElemType e)
{
	/* 判断队列是否已满 */
	if((Q->rear + 1) % MAXSIZE == Q->front)
		return ERROR;
	Q->data[rear] = e;
	/* rear指针向后移一个位置 */
	Q->rear = (Q->rear+1) % MAXSIZE;  /* 若到最后则转到头部 */
	return OK;
}
  • 出队操作:
Status DeQueue(SqQueue * Q, QElemType * e)
{
	/* 判断队列是否为空 */
	if(Q->front == Q->rear)
		return ERROR;
	/* 将队头元素赋值给e */
	*e = Q->data[Q->front];
	/* front指针向后移一位置 */
	Q->front = (Q->front + 1) % MAXSIZE;  /* 若到最后则转到头部 */
	return OK;
}

链式存储结构

  • 定义
  1. 只能尾进头出的单链表
  2. 队头指针指向链队列的头结点,而队尾指针指向终端结点。

在这里插入图片描述

  • 空队列:
    在这里插入图片描述
  • 存储结构:
typedef int QElemType;
/* 结点结构 */
typedef struct QNode
{
	QElemType data;
	struct QNode * next;
}QNode, *QueuePtr;
/* 队列的链表结构 */
typedef struct
{
	/* 队头、队尾指针 */
	QueuePtr front, rear;
}LinkQueue;
  • 入栈操作
    在这里插入图片描述

  • 出栈操作:
    在这里插入图片描述

/* 若队列不空,删除队头元素,用e返回其值,并返回OK,否则返回ERROR */
Status DeQueue(LinkQueue * Q, QElemType *e)
{
	QueuePtr p;
	if(Q->front == Q->rear)
		return ERROR;
	/* 将欲删除的队头结点暂存给p*/
	p = Q->front->next;
	/* 将欲删除的队头结点的值赋值给e */
	*e = p->data;
	/* 将原队头结点的后继p->next赋值给头结点的后继 */
	Q->front->next = p->next;
	/*若队头是队尾,则删除后将rear指向头结点*/
	if(Q->rear == p)
		Q->rear = Q->front;
	free(p);
	return OK;
}
  1. 出队操作就是将头结点的后继结点出队,将头结点改为它后面的结点。
  2. 若出队前链表除头结点外只剩下一个元素时,则需要将rear指向头结点。

循环对列与链队列的区别

  1. 循环对列是事先申请好空间,使用期间不释放,链队列在使用期间要进行申请和释放空间。
  2. 循环对列必须要有一个固定的长度,可能会产生空间的浪费,而链队列不存在这个问题。
  3. 在可以确定队列长度最大值的情况下,使用循环对列,无法预估对列 长度时,使用链队列。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

m0_46427273

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值