数据结构 4.栈和队列

1.栈(Stack)

        栈是只允许在一端进行插入或删除操作的线性表

特点:后进先出(Last In First Out )LIFO

基本操作:

 InitStack(&S):初始化栈,构造一个空栈S,分配内存空间

 DestroyStack(&L):销毁栈,销毁并释放S所占用的内存空间。

 Push(&S,x):进栈,若栈S未满,则将x加入使之成为新栈顶

 Pop(&S,&x):出栈,若栈S非空,则弹出栈顶元素,并用x返回。

 GetTop(S,&x):读栈顶元素,若栈S非空,则用x返回栈顶元素。

................

2.栈的顺序存储

//顺序栈的定义
#define MaxSize 10 //定义栈中元素的最大个数 
typedef struct{
	ElemType data[MaxSize];//静态数组存放栈中元素 
	int top; //栈顶指针 
}SqStack;

//初始化
void InitStack(SqStack &S){
	S.top=-1; //初始化栈顶指针 
} 

//判断栈空
bool isEmpty(SqStack S){
	return S.top == -1;
} 

//入栈
 bool Push(SqStack &S,ElemType x){
	if(S.top == MaxSize-1)  //栈满 
	 	return false; 
	S.top=S.top+1;  //指针+1 
	S.data[S.top] = x;  //入栈 
	return true;
 } 
 
//出栈
bool Pop(SqStack &S,ElemType &x){
	if(S.top == -1)  //栈空 
	 	return false; 
	x=S.data[S.top]; //栈顶元素出栈 
	S.top=S.top-1;  //指针-1 
	return true;
} 
//读栈顶元素
bool GetTop(SqStack S,ElemType &x){
	if(S.top == -1)
		return false;
	x=S.data[S.top];
	return true;
} 
 
 int main(){
 	SqStack S;//声明一个顺序栈(分配空间) 
 } 

   综合案例:

#include<stdio.h>
#define MaxSize 10 //定义栈中元素的最大个数 
typedef struct{
	int data[MaxSize];//静态数组存放栈中元素 
	int top; //栈顶指针 
}SqStack;

//初始化
void InitStack(SqStack &S){
	S.top=-1; //初始化栈顶指针 
} 

//判断栈空
bool isEmpty(SqStack S){
	return S.top == -1;
} 

//入栈
 bool Push(SqStack &S,int x){
	if(S.top == MaxSize-1)  //栈满 
	 	return false; 
	S.top=S.top+1;  //指针+1 
	S.data[S.top] = x;  //入栈 
	return true;
 } 
 
//出栈
bool Pop(SqStack &S,int &x){
	if(S.top == -1)  //栈空 
	 	return false; 
	x=S.data[S.top]; //栈顶元素出栈 
	S.top=S.top-1;  //指针-1 
	return true;
} 
//读栈顶元素
bool GetTop(SqStack S,int &x){
	if(S.top == -1)
		return false;
	x=S.data[S.top];
	return true;
} 
 
 int main(){
 	SqStack S;//声明一个顺序栈(分配空间) 
 	InitStack(S);
 	printf("push:");
 	if(isEmpty(S)){
 		Push(S,20);//入栈 
 		Push(S,21);
 		Push(S,22);
 		Push(S,23);
 		Push(S,24);
 		Push(S,25);
 		Push(S,26);
 		Push(S,27);
 		Push(S,28);
 		Push(S,29);
	}
	Push(S,30);//此时栈满,不再存入数据 
	//打印数据 
 	for(int i=0;i<=S.top;i++){
 		printf("%d\t",S.data[i]); 
	}
	//出栈 
	printf("\npop:\n");
	int x; 
	Pop(S,x);
	printf("%d\n",x);
	Pop(S,x);
	printf("%d\n",x);
	Pop(S,x); 
	printf("%d\n",x);
	Pop(S,x);
	printf("%d\n",x);
	//获取栈顶元素 
 	int y;
 	GetTop(S,y);
 	printf("top number:%d",y);
 } 

 结果:

push:20 21      22      23      24      25      26      27      28      29
pop:
29
28
27
26
top number:25
--------------------------------

共享栈:(栈满:top0+1==top1)

//共享栈
#define MaxSize 10 //定义栈中元素的最大个数 
typedef struct{
	ElemType data[MaxSize];//静态数组存放栈中元素 
	int top0; //栈顶指针 
	int top1;
}ShStack; 
//初始化
void InitStack(ShStack &S){
	S.top0=-1; //初始化栈顶指针 
	S.top1=MaxSize;
} 

3.栈的链式存储

//栈的链式存储
//定义 (只能在表头的位置进行插入和删除) 
typedef struct LinkNode{
	ElemType data; //数据域 
	struct LinkNode *next; //指针域 
}*LiStack;

综合案例:

//栈的链式存储
//定义 (只能在表头的位置进行插入和删除) 
#include<stdio.h>
#include<malloc.h>

typedef struct LinkNode{
	int data; //数据域 
	struct LinkNode *next; //指针域 
}*LiStack; 
void InitStack(LiStack &S){
	S=(LinkNode*)malloc(sizeof(LinkNode));
	S->next=NULL;
}

bool Insert(LiStack S,int x){
	LinkNode *p;
	p=(LinkNode*)malloc(sizeof(LinkNode));
	p->data=x;
	p->next=S->next;
	S->next=p;
	return true;
}
bool isEmpty(LiStack S){
	return S->next==NULL;
}
bool Delete(LiStack S,int &x){
	LinkNode *q;
	q=S->next;
	x=q->data;
	S->next=q->next;
	free(q);
	return true;
}


int main(){
	LiStack S;
	InitStack(S);
	if(isEmpty(S)){
		Insert(S,30);
		Insert(S,31);
		Insert(S,32);
		Insert(S,33);
		Insert(S,34);
		Insert(S,35);
	}
	LiStack p=S->next;
	while(p!=NULL){
		printf("%d\t",p->data);
		p=p->next;	
	}
	printf("\n");
	int x;
	Delete(S,x);
	printf("delete num: %d\n",x);
	Delete(S,x);
	printf("delete num: %d\n",x);
	Delete(S,x);
	printf("delete num: %d\n",x);
}

结果:

35      34      33      32      31      30
delete num: 35
delete num: 34
delete num: 33

4.队列(Queue)

        队列是只允许在一端进行插入,在另一端删除的线性表

        队尾:允许插入的一端

        队头:允许删除的一端

特点:先进先出(First In First Out)FIFO

基本操作:

 InitQueue(&Q):初始化队列,构造一个空队列。

 DestroyQueue(&Q):销毁队列,销毁并释放队列所占用的内存空间。

 EnQueue(&Q,x):入队,若队列Q未满,则将x加入使之成为新队尾

 DeQueue(&Q,&x):出队,若队列Q非空,则删除队头元素,并用x返回。

 GetHead(Q,&x):读队头元素,若队列Q非空,则将队头元素赋值给x。

................

5.队列的顺序存储

//队列的顺序存储
#define MaxSize 10
typedef struct{
	ElemType data[MaxSize]; //静态数组存放队列元素 
	int front,rear;  //队头和队尾指针 
}SqQueue; 
//初始化队列 
void InitQueue(SqQueue &Q){
	Q.front=Q.front=0;
}
//判断是否为空
bool QueueEmpty(SqQueue Q){
	return Q.front==Q.rear;
} 

//入队
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;
} 


//出队
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;
} 
//获得队头元素的值 
bool GetHead(SqQueue Q,ElemType &x){
	if(Q.rear == Q.front)
		return false;
	x=Q.data[Q.front];
	return true;
} 

//队列元素的个数:(rear+MaxSize-front)% MaxSize
int main(){
	SqQueue Q;
	InitQueue(Q); 
} 

综合案例:

//队列的顺序存储
#include<stdio.h>
#define MaxSize 10
typedef struct{
	int data[MaxSize]; //静态数组存放队列元素 
	int front,rear;  //队头和队尾指针 
}SqQueue; 
//初始化队列 
void InitQueue(SqQueue &Q){
	Q.front=Q.front=0;
}
//判断是否为空
bool QueueEmpty(SqQueue Q){
	return Q.front==Q.rear;
} 
//入队
bool EnQueue(SqQueue &Q,int x){
	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 GetHead(SqQueue Q,int &x){
	if(Q.rear == Q.front)
		return false;
	x=Q.data[Q.front];
	return true;
} 

int main(){
	SqQueue Q;
	InitQueue(Q); 
	if(QueueEmpty(Q)){
		EnQueue(Q,15);
		EnQueue(Q,16);
		EnQueue(Q,17);
		EnQueue(Q,18);
		EnQueue(Q,19);
		EnQueue(Q,20);
		EnQueue(Q,21);
	}

	int x;
	DeQueue(Q,x);
	printf("delete:%d\n",x);
	DeQueue(Q,x);
	printf("delete:%d\n",x);
	int y;
	GetHead(Q,y);
	printf("head number:%d",y);
} 

结果:

delete:15
delete:16
head number:17

6.队列的链式存储

//队列的链式存储
#include<stdio.h>
#include<malloc.h>
typedef struct LinkNode{
	ElemType 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;
}

//初始化(不带头节点) 
void InitQueue(LinkQueue &Q){
	Q.front=Q.rear=NULL;
}

//入队(带头节点)
 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;
 } 
 
 //入队(不带头节点)
 void EnQueue(LinkQueue &Q,ElemType 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;	
	} 
 } 
 //出队(带头节点)
 void DeQueue(LinkQueue &Q,ElemType &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.front=Q.rear;
	 }
	 free(p);
	 return true;
 } 
 
 
//出队(不带头节点)
 void DeQueue(LinkQueue &Q,ElemType &x){
 	if(Q.front==NULL)
 		return false;
 	LinkNode *p=Q.front;
 	x=p->data;
 	Q.front=p->next;
 	if(Q.rear == p){
 		Q.front=NULL;
 		Q.rear=NULL;
	 }
	 free(p);
	 return true;
 } 
 
//判断是否为空
bool isEmpty(LinkQueue Q){
	return Q.front == Q.rear; 
} 
int main(){
	LinkQueue Q;
	InitQueue(Q);
}

综合案例:

//队列的链式存储
#include<stdio.h>
#include<malloc.h>
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;
}

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;
 } 
 
 
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.front=Q.rear;
	 }
	 free(p);
	 return true;
 } 

bool isEmpty(LinkQueue Q){
	return Q.front == Q.rear; 
} 
int main(){
	LinkQueue Q;
	InitQueue(Q);
	if(isEmpty(Q)){
		EnQueue(Q,13);
		EnQueue(Q,14);
		EnQueue(Q,15);
		EnQueue(Q,16);
		EnQueue(Q,17);
		EnQueue(Q,18);
	}
	
	int x;
	DeQueue(Q,x);
	printf("del:%d\n",x);
	DeQueue(Q,x);
	printf("del:%d\n",x);
}

结果:

del:13
del:14

7.双端队列

        双端队列:只允许从两端插入、两端删除的线性表

        输入受限的双端队列:只允许从一端插入、两端删除的线性表

        输出受限的双端队列:只允许从两端插入、一端删除的线性表

8.栈的应用

括号匹配:

//栈的应用(括号匹配)
#include<stdio.h>
#include<stdlib.h>
#define MaxSize 10
typedef struct{
	char data[MaxSize];
	int top;
}SqStack; 

void InitStack(SqStack &S){
	S.top=-1; 
}

bool isEmpty(SqStack &S){
	return 	S.top == -1; 
}
bool Push(SqStack &S,char x){
	if(S.top == MaxSize-1)
		return false;
	S.top++;
	S.data[S.top]=x;
	return true;
}

bool Pop(SqStack &S,char &x){
	if(S.top == -1)
		return false;
	x=S.data[S.top];
	S.top--;
	return true;
}
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(isEmpty(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 isEmpty(S);
}

int main(){
	char str[]="{(()[])}";
	int len=8;
	bool flag=bracketCheck(str,len);
	printf("%d",flag); 		//打印结果:1 
}

栈在表达式中求值:

        Reverse Polish notation(逆波兰表达式=后缀表达式)

        Polish notation(波兰表达式=前缀表达式

中缀表达式:a+b (运算符在两个操作数中间)a+b-c        a+b-c*d

后缀表达式:ab+(运算符在两个操作数后面)ab+c-  /abc-+         ab+cd*-

前缀表达式:+ab(运算符在两个操作数前面)        -+abc        -+ab*cd

4a95e3f7b82c4c35a4b0ac1bac8cba53.png728dd4eb391a4effb867cb101812a448.png

栈在递归中的应用:

        最后被调用的函数最先执行结束(LIFO)

        适合“递归”算法解决:可以把原始问题转换为属性相同,但规模较小的问题

ba88878020344b78a53b46d564f78d83.png9.队列的应用

        树的层次遍历

        图的广度优先遍历

        多个进程争着使用有限的系统资源时,FCFS(First Come First Service,先来先服务)是一种常用策略

10.特殊矩阵的压缩存储 

91a7d815c2444eccb3262b4465a8a646.png

2a3ce6333605493aa760f6df8a280ffe.png

 0dbf9363cb724a7695dea0bf708f3d39.png

  • 29
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值