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

栈和队列

栈(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;
}
相关推荐
CXDNW8 分钟前
【网络面试篇】HTTP(2)(笔记)——http、https、http1.1、http2.0
网络·笔记·http·面试·https·http2.0
使者大牙9 分钟前
【大语言模型学习笔记】第一篇:LLM大规模语言模型介绍
笔记·学习·语言模型
ssf-yasuo22 分钟前
SPIRE: Semantic Prompt-Driven Image Restoration 论文阅读笔记
论文阅读·笔记·prompt
passer__jw76728 分钟前
【LeetCode】【算法】283. 移动零
数据结构·算法·leetcode
As977_31 分钟前
前端学习Day12 CSS盒子的定位(相对定位篇“附练习”)
前端·css·学习
ajsbxi34 分钟前
苍穹外卖学习记录
java·笔记·后端·学习·nginx·spring·servlet
Rattenking35 分钟前
React 源码学习01 ---- React.Children.map 的实现与应用
javascript·学习·react.js
TeYiToKu1 小时前
笔记整理—linux驱动开发部分(9)framebuffer驱动框架
linux·c语言·arm开发·驱动开发·笔记·嵌入式硬件·arm
dsywws1 小时前
Linux学习笔记之时间日期和查找和解压缩指令
linux·笔记·学习
道法自然04021 小时前
Ethernet 系列(8)-- 基础学习::ARP
网络·学习·智能路由器