栈和队列——数据结构学习笔记

栈和队列

栈(Stack)

定义与特点

栈是一种特殊的线性表,只能从一端进行插入和删除------>后进后出 LIFO结构

表尾(an) 称为栈顶Top 表头(a1)称为栈底Base

插入元素到栈顶 的操作称为入栈

删除栈顶 最后一个元素的操作称为出栈

抽象类型定义

复制代码
ADT Stack{
数据对象:
		D = {ai|ai∈ElemSet,i=1,2,3,...n,n≥0}
数据关系:
		R1 = {<ai-1,ai>|ai-1,ai∈D,i=2...,n}
		约定an端为栈顶,a1端为栈底
基本操作:
		初始化,进栈,出栈,取栈元素等
}ADT Stack

基础操作

复制代码
InitStack(&S):初始化一个空栈S。
StackEmpty(S):判断一个栈是否为空
StackLength(S):求栈长度
Push(&S, x):进栈------栈的插入操作
Pop(&S, &x):出栈------栈的删除操作
GetTop(S, &e):读栈顶元素
ClearStack(&S):栈置空
DestroyStack(&S):栈销毁

顺序栈

为方便top指针指向栈顶元素之上的下标地址

stacksize ------> 栈可使用的最大容量

空栈的标志:base == top

栈满的标志: top - base == stacksize ------------ 元素个数计算即top - base

上溢:栈满进行插入 下溢:栈空继续弹出

顺序栈的数据类型定义

复制代码
#define MAXSIZE 100
typedef struct{
		SElemType *base;//栈底指针
		SElemType *top;//栈顶指针
		int stacksize;//栈可用最大容量
}SqStack;

顺序栈的初始化

复制代码
Status lnitStack(SqStack &S)
{
	S.base = new SElemType[MAXSIZE];
	if(!S.base) exit (OVERFLOW);//存储分配成功
	S.top = S.base;
	S.stacksize = MAXSIZE;
	return OK;
}

判断顺序栈是否为空

复制代码
Status StackEmpty(SqStack S)
{
	if(S.top == S.base)
		return TURE;
	else
		return FALSE;
}

求顺序栈的长度

复制代码
int StackLength(SqStack S)
{
	return S.top - S.base;
}

清空顺序栈

复制代码
Status ClearStack(SqStack S){
	if(S.base) S.top = S.base;
	return OK;
}

销毁顺序栈

复制代码
Status DestroyStack(SqStack &S){
	if(S.base){
		delete S.base;
		S.stacksize == 0;
		S.base = S.top = NULL;
	}
	return OK;
}

顺序栈的入栈

1.判断栈是否满,若满则出差(上溢)

2.元素e压入栈顶

3.栈顶指针加1

复制代码
Status Push(SqStack &S, SElemType e){
	if(S.top - S.base == S.stacksize)
		return ERROR;
	*S.top++ = e;	//先e赋值给*S.top再移动指针++
	return OK;
	}
}

顺序栈的出栈

1.判断栈是否为空,空则出错(下溢)

2.获取栈顶元素e

3.栈顶指针-1

复制代码
Status Pop(SqStack &S, SElemType &e){
	if(S.top == S.base)
		return ERROP;
	e = *--S.top;
	return OK;
}

链栈

链栈指针方向与链表方向相反

· 链表的头指针就是栈顶

· 不需要头节点

· 基本不存在栈满的情况

· 空栈相当于头指针指向空

· 插入和删除仅在栈顶处执行

数据类型定义

复制代码
typedef struct StackNode{
	SElemType date;
	struct StackNode *next;
}StackNode,*LinkStack;
LinkStack S;

初始化

复制代码
void lnitStack(LinkStack &S){
	S = NULL;
	return OK;
}

判断链栈是否为空

复制代码
Status StackEmpty(LinkStack S){
	if(S == NULL) return TURE;
	else return FlASE;
}

链栈入栈

复制代码
Status Push(LinkStac &S,SElemType e){
	p = new StackNode;
	p -> date = e;
	P -> next = S;
	S = p;
	return OK;
}

链栈出栈

复制代码
Status Pop(LinkStac &S,SElemType &e){
	if(S == NULL) return ERROR;
	e = S -> date;
	p = S;
	S = S -> next;
	delete p;
	return OK;
}

取栈顶元素

复制代码
SElemType GetTop(LinkStack S){
	if(S!= NULL)
		return S -> date;
}

栈与递归

一个对象包含自己或自己给自己定义

一个过程直接或间接调用自己

分治法求递归问题算法的一般形式

复制代码
void p(参数表){
	if(递归结束条件) 可以直接求解步骤; ------基本项
	else p(较小的参数);  ------归纳项  
}

队列(queue)

队列是一种先进先出的线性表(FIFO)

一端插入一端删除

抽象类型定义

复制代码
ADT Queue{
数据对象:
		D = {ai|ai∈ElemSet,i=1,2,3,...n,n≥0}
数据关系:
		R1 = {<ai-1,ai>|ai-1,ai∈D,i=2...,n}
		约定a1端为队列头,an端为队列尾
基本操作:
		初始化,入队,出队等
}ADT Queue

基础操作

复制代码
InitQueue (&Q)    构造空队列
DestroyQueue (&Q)  销毁队列
ClearQueue (&Q)      清空队列
QueueEmpty(Q)       判空. 空=TRUE,
QueueLength(Q)      取队列长度
GetHead (Q,&e)      取队头元素,
EnQueue (&Q,e)      入队列
DeQueue (&Q,&e)     出队列
QueueTraverse(Q,visit())      遍历

顺序队列

一维数组base[MAXQSIZE]表示

复制代码
#define MAXQSIZE 100 //最大队列长度
Typedef struct{
		QElemType *base; //初始化的动态分配存储空间
		int front;	//头指针
		int rear; //尾指针
}SqQueue

初始状态 front = rear = 0

rear = MAXQSIZE 时发生溢出

front = 0 rear = MAXQSIZE时再入队 则为真溢出

front != 0 rear = MAXQSIZE时再入队 则为假溢出

对于假上溢如何解决 >>>

复制代码
1.将对内元素依次向队头方向移动 (浪费时间)
2.循环:
		思路:base[0] 接在 base[MAXQSIZE-1] 之后 ,若 rear + 1 == MAXQSIZE, 则令 rear = 0;
		具体实现:用%的运算
插入元素:Q.base[Q.rear] = x;
		Q.rear = (Q.rear + 1) % MAXQSIZE;
删除元素:x = Q.base[Q.front]
		Q.front = (Q.front + 1 ) % MAXQSIZE

对于判断循环队空队满 >>>

复制代码
当循环队列中队空队满都为 front == rear 如何解决
1.设标记
2.记录个数
3.少用一个元素空间 则队满: (rear + 1) % MAXQSZIE == front

初始化

复制代码
Status lnitQueue(SqQueue &Q){
	Q.base = new QElemType[MAXQSIZE];
	if(!Q.base) exit(OVERFLOW);
	Q.front = Q.rear = 0;
	return OK;
}

求队列长度

复制代码
int QueueLength(SqQueue Q){
	return ((Q.rear - Q.front + MAXQSZIE) % MAXQZIE);
}

入队

复制代码
Status EnQueue(SqQueue &Q, QElemType e){
	if((Q.rear + 1) % MAXQSIZE == Q.front) return ERROR;
	Q.base[Q.rear] = e;
	Q.rear = (Q.rear + 1) % MAXSIZE;
	return OK;
}

出队

复制代码
Status DeQueue(SqQueue &Q, QElemType &e){
	if(Q.rear = Q.front) return ERROR;
	e = Q.base[Q.front];
	Q.front = (Q.front + 1) % MAXQSZIE;
	return OK;
} 

取队头元素

复制代码
SElemType GetHead(SqQueue Q){
	if(Q.rear = Q.front)
		return Q.base[Q.front];
} 

链队

当无法估计长度时,则宜采用链队列

类型定义

复制代码
#define MAXQSIZE 100
typedef struct Qnode{
	QElemType data;
	stuct Qnode *next;
}QNode,*QueuePtr;

typedef struct{
	QueuePtr front;
	QueuePtr rear;
}LinkQueue;

初始化

复制代码
Status lnitQueue(LinkQueue &Q){
	Q.front = Q.rear = (QueuePtr)malloc(sizeof(QNode));
	if(!Q.front) exit(OVERFLOW);
	Q.front -> next = NULL;
	return OK;
}

销毁链队列

复制代码
Status DestroyQueue(LinkQueue &Q){
	while(Q.front){
		p = Q.front -> next;
		free(Q.front);
		Q.front = p;
	}//Q.rear = Q.front -> next; free(Q.front); Q.front = Q.rear;
	return OK;
}

入队

复制代码
Status EnQueue(LinkQueue &Q, QElemType e){
	p = (QueuePtr)malloc(sizeof(QNode));
	if(!p) exit(OVERFLOW);
	p -> data = e;
	p -> next = NULL;
	Q.rear -> next = p;
	Q.rear = p;
	return OK;
}

出队

复制代码
Status DeQueue(LinkQueue &Q, QElemType e){
	if(Q.front == Q.rear) return ERROR;
	p = Q.front -> next;
	e = p -> data;
	Q.front -> next = p ---> next;
	if(Q.rear == p) Q.rear = Q.front;
	delepe p;
	return OK;
}

求链队列的队头元素

复制代码
Status GetHead(LinkQueue Q, QElemType &e){
	if(Q.front == Q.rear) return ERROR;
	e = Q.front -> next -> data;
	return OK;
}
相关推荐
Java技术实践几秒前
JPA 用 List 入参在 @Query中报错 unexpected AST node: {vector}
数据结构·windows·list
陌路20几秒前
S4双向链表
数据结构·链表
知识分享小能手2 分钟前
uni-app 入门学习教程,从入门到精通,uni-app组件 —— 知识点详解与实战案例(4)
前端·javascript·学习·微信小程序·小程序·前端框架·uni-app
wahkim10 分钟前
Flutter 学习资源及视频
学习
摇滚侠20 分钟前
Spring Boot 3零基础教程,WEB 开发 Thymeleaf 属性优先级 行内写法 变量选择 笔记42
java·spring boot·笔记
摇滚侠24 分钟前
Spring Boot 3零基础教程,WEB 开发 Thymeleaf 总结 热部署 常用配置 笔记44
java·spring boot·笔记
2401_8414956427 分钟前
【数据结构】最长的最短路径的求解
java·数据结构·c++·python·算法·最短路径·图搜索
泡沫冰@29 分钟前
数据结构(5)
数据结构
小白要努力sgy1 小时前
待学习--中间件
学习·中间件
第七序章1 小时前
【C + +】红黑树:全面剖析与深度学习
c语言·开发语言·数据结构·c++·人工智能