数据结构 栈与队列

栈与队列

1.定义:仅在表尾进行插入与删除操作的线性表
2.原理:允许插入与删除的一端称为栈顶,另一端称为栈底,不含任何元素称为空栈;属于后入先出结构(Last in First out)
抽象数据类型如下:

ADT 栈(stack)
Date
同线性表。元素具有相同的类型,相邻元素间有前驱和后继的关系
Operation
初始化操作,建立一个空栈;
判断栈是否为空
判断栈是否为满
删除并返回栈顶元素
将元素压入栈
3.实现:
(1)顺序存储结构及其实现
栈结构及其定义

#define MAXSIZE <栈能存储的最大元素个数>
typedef struct Snode * Stack; 
struct SNode{
	Elementtype Date[MAXSIZE];
	int top;//栈顶元素位置变量
}

初始化操作,建立一个空栈;

void InitStack(Stack S)
{
	S->top=-1;
}

入栈

void Push(Stack S,Elenmenttype e)
{
	if(MAxsize-1==S->top){
		printf("栈满了");
		return ;
	}
	else{
		S->Date[++S->top]=e;
		return ;
	}
}

出栈

void Pop(Stack S,Elenmenttype *e)
{
	if(-1==S->top){
		printf("栈空");
		return ;
	}
	else{
		*e=S->Date[S->top--};
		return ;
	}
}

两栈共享存储空间(通过flag判定操作哪一个栈)87```c
typedef DStack *S;
struct DStack{
Elenmenttype Date[MAXSIZE];
int top1;
int top2;
};
//初始化top1=-1;top2=MAXSIZE-1;

入栈

```c
void DPush(DStack S,Elementtype e,int flag)
{
	if(S->top2-1==S->top1){
		printf("栈满了\n");
		return ;
	}
	else{
		if(flag==1)
			S->Date[++S->top1]=e;
		if(falg==2)
			S->Date[--S->top2]=e;
		return ;
	}
}

出栈

void DPop(DStack S,Elementtype *e,int flag)
{
	if(flag==1){
		if(S->top1==-1){
			printf("栈1空的\n");
			return ;
		}
		*e=S->Date[S->top1--];
	}
	else if(flag==2){
		if(S->top2==MAXSIZE){
			printf("栈2空的\n");
			return ;
		}
		*e=S->Date[S->top2++];
}

(2)链式存储结构及其实现
栈结构及其定义

  链式结构的堆栈在哪一端进行push pop呢?即栈顶指针应该在链表的哪一头?
  		答:因为链表存在头指针,而栈存在栈顶指针,故将两者合二为一,故将链表头部作为栈顶
typedef struct StackNode{
	Elementtype Date;
	struct StackNode *next;//可以用非完全类型定义指针
}StackNode,*LinkStackPtr;
//定义链式堆栈需要栈顶指针,该指针指向一个结点
typedef struct LinkStack{
	LinkStackPtr top;
	int count;//统计当前堆栈元素个数
}LinkStack;

入栈

void Push(LinkStack *S,Elementtypye e)
{
	LinkStackPtr P=(LinkStackPtr)malloc(sizeof(Stacknode));
	P->Date=e;
	P->Next=S->top;
	S->top=P;
	S->count++;
	return ;
}

出栈

void Pop(LinkStack *S,Elementtypye *e)
{
	LinkStackPtr P=S->top;
	*e=S->top->Date;
	S->top=S->top->Next;
	free(P);
	S->count--;
	return ;
}

4.应用:
多项式的四则计算:
(1)计算机是通过将多项式后缀表达式中数字扔进堆栈中进行运算;
(2)如何将中缀表达式变为后缀表达式? 将多项式中的符号扔进堆栈;

队列

1.定义:只允许一端(队尾)进行插入操作,另一端(队头)进行删除的线性表;属先进先出结构(First in First out)
2.实现
(1)顺序存储实现

由一个队列头位置变量,一个队列尾位置变量,一个一位数组描述

顺序队列容易出现假溢出现象,即队尾溢出,但队头位置空闲,故采用循环队列(队列头尾相接)!
在这里插入图片描述

此时如何判定满?(此时空置一个元素)
(rear+1)%MAXSIZE==front
如何判定空?
rear==front
如何确定当前队列长度?
front<rear时:rear-front
front>rear时:rear+MAXSIZE-front
故总结起来就是
(MAXSIZE-front + rear)%MAXSIZE

顺序存储结构实现形式

typedef struct Qnode*Queue;
struct Qnode
{
	Elementtype Date[MAXSIZE];
	int rear;
	int front;
};
//初始化队列
void InitQueue(Queue Q)
{
	Q->front=0;
	Q->rear=0;
	return ;
}
//插入
void AddQueue(Queue Q,Elenmenttype e)
{
	if((Q->rear+1)%MAXSIZE==Q->front){
		printf("队列满了");	
		return ;
	}
	Q->Date[Q->rear]=e;
	Q->rear=(Q->rear+1)%MAXSIZE;
	return ;
}
//队头删除
void AddQueue(Queue Q,Elementtype *e)
{
	if(Q->rear==Q->front){
		printf("队空");	
		return ;
	}
	*e=Q->Date[Q->front];
	Q->front=(Q->front+1)%MAXSIZE;
	
	return ;
}

(2)链式存储实现
链式存储结构的队列其实就是单链表,只不过有一点特殊之处是:不同于普通单链表可以在任意位置插入与删除(位置合法)链式存储结构的队列只能尾进头出。

总的来说,如果可以确定队列的最大值,建议用循环队列,如果不能预估队列的长度,则用链队列。

typedef struct Qnode{
	Qelementtype date;
	struct Qnode *next;
}QNode,*QueuePtr;

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

入队列

void EnQueue(LinkQueue *Q,Qelementtype e)
{
	QueuePtr s=(QueuePtr)malloc(sizeof(Qnode));
	if(!s)//分配内存失败
		exit(OVERFLOW);
	s->data=e;
	s->next=NULL;
	Q->rear->next=s;
	Q->rear=s;	
}

出队列

void DeQueue(LinkQueue *Q,Qelementtype *e)//该队列有头结点
{
	QueuePtr p;
	if(Q->front==Q->rear)
		printf("空队列");
	p=Q->front->next;//将与删除的队列的第一个节点赋给p
	*e=p->data;
	Q->front->next=p->next;
	
	free(p);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值