栈与队列

栈与队列

1.栈

线性表的一种,插入与删除只允许在一端进行操作
术语:栈顶,桟低,空栈
特点:后进先出(LIFO,Last in First Out)
进栈顺序:a->b->c->d->e
出栈顺序:后进先出
(1)所有元素都近栈后出栈:e->d->c->b->a;
(2)进栈出栈穿插:b->e->d->c->a;
总结:有N个元素入栈,则有卡特兰数
1 n + 1 C 2 m m ( 2 m 在 下 , m 在 上 ) \frac{1}{n+1}C^m_2m(2m在下,m在上) n+11C2mm(2mm)
例如 3个元素入栈则有5种出栈情况

1.1顺序栈-栈的大小不可变

定义+初始化
#define MaxSize 10
//定义
typedef struct{
	ElemType data[MaxSize];
	int top0;
	int top1;//共享栈指针
}SqStack;
//初始化
void InitStack(SqStack &S){
	S.top0=-1;
	S.top1=MaxSize;//共享栈指针在最上方,从最上方插入元素
}
判空操作
bool Elmpy(SqStack S){
	if(S.top0==-1 && S.top1==MaxSize)
		return true;
	else
		return false;
}//栈满的条件:S.top0+1==S.top1
进栈操作
bool Push(SqStack &S,ELempType i){
	if(S.top==MaxSize-1)
		return false;
	S.top0=S.top0+1;
	S.data[S.top0]=i;
//以上两步等价与S.data[++S.top0]=i;//注意++S.to0p与S.top0++不一样,前者是先加一后调用,后者先调用后top0加1
	return true;
}
出栈操作
bool Pop(SqStack &S,int &x){
	if (S.top0==-1)
		return false;
	x=S.data[S.top0];
	S.top0=S.top0-1;//x=S.data[S.top0--];
}
读取栈顶元素
bool ReadTop(SqStack S,int &x){
	if(S.top0==-1)
		return false;
	x=S.data[S.top0];
	return true;
}

1.2 链栈(链式存储结构)

//定义
typedef struct LinkNode{
	ElemType data;
	struct LinkNode *next;
}*LiStack;
//其余详见单(双)链表

2.队列

只允许在一端插入,另一端进行删除操作。
特点:先进先出(FIFO:First In First Out)
术语:队头、队尾、空队列
计算元素个数:(rear+MaxSize-front)%MaxSize

2.1顺序存储

定义和初始化静态队列
#define MaxSize 10
typedef struct{
	ElemType data[MaxSize];
	int front,rear;//声明队头和队尾指针
}SqQueue;
void InitQueue(SqQueue &Q){
	Q.rear=Q.front=0;//初始都指向0,Q为在main函数下声明的队列
}
入队操作
bool EnQueue(SqQueue &Q ,int e){
	if ((Q.rear+1)%MaxSize==Q.front)//队尾指针的下个指针
		return false;
	Q.data[Q.rear]=x;
	Q.rear=(Q.rear+1)%MaxSize;//亦可称为循环队列
	return true;
}
出队操作
bool DeQueue(SqQueue &Q,int &x){
	if (Q.rear==Q.front)//判断是否为空
		return false;
	x=Q.data[Q.front];
	Q.front=(Q.front+1)%MaxSize;
	return true;
}

#### 获取元素

bool GetQueue(SqQueue &Q,int &x){
	if (Q.rear==Q.front)//判断是否为空
		return false;
	x=Q.data[Q.front];
	return true;
}

2.2队列的链式存储

定义和初始化
//带头结点
typedef struct LinkNode{
	int data;
	struct LinkNode *next;
}LinkNode;
typedef struct{
	LinkNode *front,*rear;
}LinkQueue;
void InitQueue(LinkQueue &Q){
	Q.front=Q.rear=(LinkNode*)malloc(sizeof(LinkNode));
	Q.front->next=NULL;
}
//判空
bool IsEmpty(LinkQueue Q){
	if (Q.front==Q.rear)
		return true;
	else
		return false;
}
//不带头结点
void InitQueue(LinkQueue &Q){
	Q.front=NULL;
	Q.rear=NULL;
}
//判空
bool IsEmpty(LinkQueue Q){
	if (Q.front==NULL)
		return true;
	else
		return false;
}
入队操作
//带头结点
void EnQueue(LinkQueue &Q,int x){
	LinkNode *s=(LinkNode *)malloc(sizeof(LinkNode));
	s->data=x;
	s->next=NULL;
	Q.rear->next=s;
	Q.rear=s;
}
//不带头结点
void EnQueue(LinkQueue &Q,int x){
	LinkNode *s=(LinkNode *)malloc(sizeof(LinkNode));
	s->data=x;
	s->next=NULL;
	if(Q.front==NULL){
		Q.front=s;
		Q.rear=s;
	}
	else{
        Q.rear->next=s;
        Q.rear=s;
	}
}
出队操作
//带头结点
bool DeQueue(LinkQueue &Q ,int &x){
	if (Q.front==Q.rear)
		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);
	return true;
}
//不带头结点
bool DeQueue(LinkQueue &Q ,int &x){
	if (Q.front==NULL)
		return false;
	LinkNode *p=Q.front;
	x=p->data;
	Q.front->next=p->next;
	if (Q.rear==p)
		Q.rear=NULL;
		Q.front=NULL;
	free(p);
	return true;
}

2.3双端队列

输入受限与输出受限的双端队列

3.栈与队列的应用

3.1栈在括号匹配中的应用
bool bracketCheck(char str[] ,int length){
	SqStack S;
	InitStack(S);//初始化栈
	for(int i=0;i<length;i++){
		if(str[i]=='('||str[i]=='['||str[i]=='{'){
			Push(S,str[i]);}//左括号入栈
		else{
			if (StackEmpty(S))return false;//判断栈空
			char topElem;
			Pop(S,topElem);//栈顶元素出栈
			if (str[i]==')'&&topElem!='(')return false;
			if (str[i]==']'&&topElem!='[')return false;
			if (str[i]=='}'&&topElem!='{')return false;
		}
		}
		return StackEmpty(S);
}
3.2栈的表达式求值

1.三种算术表达式:中缀表达式、前缀表达式(波兰表达式)、后缀表达式(逆波兰表达式)(√)
中缀表达式:a+b,运算符在操作数中间;a+b-c;a+b-cd
后缀表达式:ab+,运算符在操作数后面;ab+c-/abc-+;ab+cd
-
前缀表达式:+ab,运算符在操作数之前;-+abc/±bca;-+abcd
中缀转后缀【左优先原则:只要左边的运算符能先计算,就优先算左面的 】

中缀转前缀【右优先原则:只要右边的运算符能先计算,就优先算右面的】
中缀表达式求值:
(1)初始化两个栈。操作数栈,运算符栈
(2)扫描,按次序压入栈中,并按照左优先原则进行算数

3.3 栈在递归的调用

函数调用栈

3.4队列的应用
(1)树的层次遍历
(2)图的广度优先遍历
(3)在操作系统中进行FCFS(先来先服务)
3.5特殊矩阵的压缩存储
//一维数组
ElemType a[10];//各数组元素大小相同,物理上连续存放
//a[i]存放地址=loc+i*sizeof(ElemType);i从0开始
//二维数组
ElemType a[2][4];//两行四列;行优先与列优先
//b[i][j]存储地址=Loc+(i*N+j)*sizeof(ElemType)行优先(N为列)
//b[i][j]存储地址=Loc+(j*M+i)*sizeof(ElemType)列优先(M为行)

特殊矩阵:
(1)对称矩阵:若n阶方阵中对任意一个元素恒有Ai,j=Aj,i,则该矩阵为对称矩阵
主对角线i=j;上三角区;i<j;下三角区:i>j
(2)三角矩阵:
(3)三对角矩阵:带状矩阵;当|i-j|>1,有Ai,j=0
(4)稀疏矩阵:非零元素远远小于矩阵元素个数:顺序存储(<行,列,值>)
十字链表法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值