三.栈与队列

栈与队列

一.栈(stack)

A.前知(定义+基本操作)

(后进先出=last in first out=LIFO)
在这里插入图片描述

创,销
1.Initstack(&S)
2.Destroystack(&S)

增,删
3.Push(&S,x)
4.pop(&S,&x)


5.Gettop(S,&x)

是否空
6.Stackempty(S)

B.栈的顺序存储----------图片

在这里插入图片描述

=======================================

+++++++++++++顺序栈的两种实现+++++++++++++

=======================================

1. top=-1情况:

a1.定义typedef struct

#define maxsize 10
typedef struct 
{
	elemtype data[maxsize];//静态数组存放元素 
	int top;  //栈顶指针 
} sqstack;//sequence顺序

int main()
{
	sqstack s;//用声明顺序栈(分配空间) 
} 

a2.初始化操作Initstack(sqstack &s)

void Initstack(sqstack &s)
{
	s.top =-1;
} 

a3.是否栈空stackempty(sqstack s)

bool stackempty(sqstack s)
{
	if(s.top ==-1)return true;//空 
	else return false;//不空 
}

a4.是否栈满stackfull(sqstack s)

bool stackfull(sqstack s)
{
	if(s.top ==maxsize-1)return true;//栈满
	else return false;//栈不满 
}

a5.进栈操作push(sqstack &s,elemtype x)

bool push(sqstack &s,elemtype x)
{
	if(s.top ==maxsize-1)return false;//栈满
	s.top =s.top +1;//指针先加1 
	s.data [s.top ]=x;//新元素入栈 
	//等价于s.data[++s.top]=x 
	return true;	
} 

a6.出栈操作pop(sqstack &s,elemtype &x)

bool pop(sqstack &s,elemtype &x)
{
	if(s.top=-1)return false;//栈空
	x=s.data [s.top ]//栈顶元素先出栈 
	s.top =s.top -1;//数据还存留在内存,只是逻辑上删除 
	//等价于x=s.data [s.top--] 
	return true;
}

a7.读取栈顶元素Gettop(sqstack s,elemtype &x)

bool Gettop(sqstack s,elemtype &x)
{
	if(s.top ==-1)return false;//栈空 
	x=s.data [s.top ];//栈顶元素 
	return true;	
}

=======================================

2. top=0的情况:

b1.定义typedef struct

#define maxsize 10
typedef struct 
{
	elemtype data[maxsize];//静态数组存放元素 
	int top;  //栈顶指针 
} sqstack;//sequence顺序

int main()
{
	sqstack s;//用声明顺序栈(分配空间) 
} 

b2.初始化操作Initstack(sqstack &s)

void Initstack(sqstack &s)
{
	s.top =0;
} 

b3.是否栈空stackempty(sqstack s)

bool stackempty(sqstack s)
{
	if(s.top ==0)return true;//空 
	else return false;//不空 
}

b4.是否栈满 stackfull(sqstack s)

bool stackfull(sqstack s)
{
	if(s.top ==maxsize)return true;//栈满
	else return false;//栈不满 
}

b5.进栈操作push(sqstack &s,elemtype x)

bool push(sqstack &s,elemtype x)
{
	if(s.top ==maxsize)return false;//栈满
	s.data [s.top ]=x;//新元素入栈 
	s.top =s.top +1;//指针加1 
	//等价于s.data[s.top++]=x 
	return true;	
} 

b6.出栈操作pop(sqstack &s,elemtype &x)

bool pop(sqstack &s,elemtype &x)
{
	if(s.top=0)return false;//栈空
	s.top =s.top -1;//数据还存留在内存,只是逻辑上删除 
	x=s.data [s.top ]//栈顶元素出栈 
	//等价于x=s.data [--s.top] 
	return true;
}

b7.读取栈顶元素Gettop(sqstack s,elemtype &x)

bool Gettop(sqstack s,elemtype &x)
{
	if(s.top ==0)return false;//栈空 
	x=s.data [s.top -1];//栈顶元素 
	return true;	
}

=======================================

+++++++++++共享栈(顺序栈的一种)++++++++++

=======================================

c1.定义

#define maxsize 10
typedef struct 
{
	elemtype data[maxsize];//静态数组存放元素 
	int top0;  //0号栈栈顶指针 
	int top1;  //1号栈栈顶指针  
} shstack;     //share

int main()
{
	shstack s;//用声明顺序栈(分配空间) 
} 

c2.初始化

void Initstack(sqstack &s)
{
	//初始栈顶指针 
	s.top0 = -1;
	s.top1 = maxszie;
} 

c3.是否栈满

bool stackfull(shstack s)
{
	if(s.top0+1=s.top1)return true;//栈满
	else return false;//栈不满 
}

=======================================

C.栈的链式存储--------图片(与单链表类似)

在这里插入图片描述

1.定义

typedef struct Linknode
{
	elemtype data;
	struct Linknode* next;
}*Listack;

2.其他请自行实现

二.队列

A.前知(定义+基本操作)

先进先出=first in first out=FIFO
在这里插入图片描述

创,销
1.Iniqueue(&S)
2.Destroyqueue(&S)

增,删
3.Enqueue(&S,x)入队
4.Dequeue(&S,&x)出队


5.Gethead(S,&x)访问队头

是否空
6.Stackempty(S)

B.队列的顺序存储-------图片

在这里插入图片描述

1.定义typedef struct

#define  maxsize  10
typedef struct 
{
	elemtype data[maxsize];
	int front,rear;
}sqqueue;


int main()
{
	sqqueue q;
	
}

2.初始化

//初始化 
void Initqueue(sqqueue &q)
{
	//队头,队尾指针指向0 
	q.front =q.rear =0;
}

3.队列是否空

bool queueempty(sqqueue s)
{
	if(q.front==q.rear)	return true;//空
	else return false;//不空 
} 

4.入队(因为涉及判满------从这里开始逐步循环队列化)

如何判断队列已满呢
此处让if(rear==maxsize)判断的话是错误的,如下图这种情况:
在这里插入图片描述

//入队 
bool Enqueue(sqqueue &q,elemtype x)
{
	if(队列已满)return false;// 队列满,报错 
	q.data [q.rear ]=x;//x插入队尾 
	q.rear =q.rear +1;//队尾指针向后移动 
	return true; 
}

那么如何判断是否满呢?
如上图中:data[0] data[1] data[2]未满
那就使q.rear =(q.rear +1)%maxsize
此时rear=(9+1)%10=0 ,那么此时的队列变为循环队列

//入队 
bool Enqueue(sqqueue &q,elemtype x)
{
	if(队列已满)return false;// 队列满,报错 
	q.data [q.rear ]=x;//x插入队尾 
	q.rear =(q.rear +1%maxsize;//(加1)%10
	return true; 
}

++++++++++++++++++循环队列++++++++++++++

=======================================

D1.循环队列--------关键代码%

	q.data [q.rear ]=x;//x插入队尾 
	q.rear =(q.rear +1%maxsize;//(加1)%10

D2.循环队列 --------是否空queueempty(sqqueue s)

bool queueempty(sqqueue q)
{
	if(q.front==q.rear)	return true;//空
	else return false;//不空 
}

D3.循环队列---------入队Enqueue(sqqueue &q,elemtype x)

//入队 
bool Enqueue(sqqueue &q,elemtype x)
{
	if((q.rear + 1)%maxsize==q.front )return false;// 队列满,报错 
	
	q.data [q.rear ]=x;//x插入队尾 
	q.rear =(q.rear + 1)%maxsize//队尾指针向后移动 
	return true; 
}

D4.循环队列--------出队Dequeue(sqqueue &q,elemtype &x)

//出队 
bool Dequeue(sqqueue &q,elemtype &x)
{
	if(q.front ==q.rear )return false;//队空报错 
	x=q.data [q.front ];//引用x赋值返回 
	q.front =(q.front +1)%maxsize;//指针后移 
	return true; 
}

D5.循环队列--------读取队头元素

bool Gethead(sqqueue q,elemtype &x)
{
	if(q.front ==q.rear )return false;//队空报错
	x=q.data [q.front ];
	return true;	
} 

D6.循环队列--------判断循环队列满/空

	此时判断错误
	空:q.front==q.rear
	满:q.front==q.rear
	

那么如何判断呢?如下三个方法

方法一.浪费一个空间
初始化:front=rear=0

满:(q.rear + 1)%maxsize==q.front
空:q.front ==q.rear

队列元素个数:(rear+maxsize-front)%maxsize
方法二.不浪费,定义size
初始化:front=rear=0,size=0

插入成功:size++
删除成功:size--

满:size=maxsize
空:size=0
方法三.不浪费,定义tag
初始化:front=rear=0,tag=0

每次删除成功:tag=0
每次插入成功:tag=1
满:front==rear&&tag==1
空:front==rear&&tag==0

D7.循环队列----------rear的不同指向

1.rear=0(rear指向队尾元素的后一个位置)
a.初始化
//初始化 
void Initqueue(sqqueue &q)
{
	//队头,队尾指针指向0 
	q.front =q.rear =0;
}
b.入队-----关键code
	q.data [q.rear ]=x;//x插入队尾 
	q.rear =(q.rear + 1)%maxsize//队尾指针向后移动 
c.出队操作相同-----关键code
	x=q.data [q.front ];//引用x赋值返回 
	q.front =(q.front +1)%maxsize;//指针后移 
d.判空-----关键code
	浪费一个空间的判空,判满
	空:q.front==q.rear
	满:(q.rear + 1)%maxsize==q.front
2.rear=maxsize-1(rear指向队尾元素)
a.初始化
//初始化 
void Initqueue(sqqueue &q)
{
	//队头,队尾指针指向0 
	q.front  = 0;
	q.rear  = maxsize-1;
}
b.入队-----关键code
	q.rear =(q.rear + 1)%maxsize//队尾指针先向后移动 
	q.data [q.rear ]=x;//x插入队尾 
c.出队操作相同-----关键code
	x=q.data [q.front ];//引用x赋值返回 
	q.front =(q.front +1)%maxsize;//指针后移 
d.判空、判满-----思路+关键code+思路
	此时无法判断
	空:(q.rear + 1)%maxsize==q.front
	满:(q.rear + 1)%maxsize==q.front
	

	换思路:
	1.浪费一个空间
	空:(q.rear + 1)%maxsize==q.front
	满:(q.rear + 2)%maxsize==q.front
	2.定义size
    空:size=0	
    满:size =maxsize
	3.定义tag
	空:(q.rear + 1)%maxsize==q.front&&tag=0(删除)
	满:(q.rear + 1)%maxsize==q.front&&tag=1(插入)

=======================================

C.队列的链式存储-------图片

在这里插入图片描述

1.定义typedef struct

typedef struct Linknode
{
	elemtype data;
	struct Linknode *next;	
} Linknode;

typedef struct 
{
	Linknode *front,*rear;//队头,队尾 
}Linkqueue;

2.初始化----带头结点

//初始化
void Initqueue(Linkqueue &q) 
{
	q.front =q.rear =(Linknode*) malloc(sizeof(Linknode));
	q.front ->NULL;
}

3.初始化----不带头结点

//初始化
void Initqueue(Linkqueue &q) 
{
	q.front = NULL
	q.rear = NULL;
}

4.判空----带头结点

bool Isempty(Linkqueue &q)
{
	//或者q.front->next=NULL
	if(q.front == q.rear )return true;
	else return true;
} 

5.判空----不带头结点

bool Isempty(Linkqueue &q)
{
	//或者q.rear=NULL 
	if(q.front == NULL)return true;
	else return true;
}

6.入队----带头结点

//入队 
void Enqueue(Linkqueue &q,elemtype x)
{
	Linknode * s=(Linknode *)malloc(sizeof(Linknode));
	s->data=x;
	s->next==NULL;
	q.rear ->next=s;//新节点插入到rear之后 
	q.rear =s;//修改表尾指针 
	
}

7.入队----不带头结点

//入队
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;//新节点插入rear之后
		q.rear =s;//修改rear指针
	}
}

8.出队----带头结点

//出队 
bool Dequeue(Linkqueue &q,elemtype &x)
{
	if(q.front ==q.rear )return false;//空队
	Linknode * p=q.front ->next;
	x=p->data; //返回x
	q.front ->next=p->next;//修改头结点的next指针
	if(q.rear ==p) q.rear =q.front ;//最后一个结点出队,修改rear指针
	free(p);
	return true;
}

9.出队----不带头结点

//出队	
bool Dequeue(Linkqueue &q,elemtyoe &x)
{
	if(q.front == NULL)return false;//空队	
	Linknode *p=q.front;//P指向此次出队的结点 
	x=p->data;//返回x 
	q.front =p->next;//修改front指针 
	if(q.rear ==p)//此次是最后一个结点出队 
	{
		q.front =NULL;//front,rear指向NULL 
		q.rear =NULL;	
	}  
	free(p);
	return true;
}

10.判满----顺序存储/链式存储

顺序存储:预分配的空间耗尽则满
链式存储:一般不队满,除非没内存

D.双端队列(一般考察序列合法性)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

三.应用

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿斯卡码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值