栈、队列的应用(栈实现队列,队列实现栈,球钟问题)

栈、队列的应用 C语言

1.用两个栈来实现一个队列

1.两个栈,s1,s2
2.入队:找到空s1栈,入栈,若无空栈,则出栈s1中的所有元素,存到另一栈s2中,再入栈s1。
3.出队:非空栈出栈。

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

typedef int DataType;

//数据节点结构体
typedef struct node
{
	DataType data;		//数据
	struct node *next;	//指针
}LinkNode;

//管理结构体
typedef struct stack
{
	struct node *top;		//栈顶偏移 栈顶指针就是节点指针的类型
	unsigned int size;				//当前元素个数
}Stack;


//初始化链式栈
Stack * InitStack()
{
	Stack * s = malloc(sizeof(Stack));
	if(s!=NULL)
	{
		s->top=NULL;
		s->size=0;
		return s;
	}
}

// 压栈、出栈、栈空判断
bool IsStackEmpty(Stack *s)
{
	return (s->size == 0);
}

bool push(Stack *s,DataType data)
{
	LinkNode *newNode = malloc(sizeof(LinkNode));
	if(newNode!=NULL)
	{
		//新节点初始化
		newNode->data = data;
		//新节点next指向原来栈顶
		newNode->next = s->top;
		//将栈顶设置为新节点
		s->top=newNode;
		//元素个数加1
		s->size++;
		return true;
	}
	return false;
}


bool pop(Stack *s,DataType *data)
{
	if(IsStackEmpty(s)||s==NULL)
	{
		return false;
	}
	//先拿到栈顶的数据
	*data = s->top->data;
	//将栈顶往后(向下)偏移一个
	s->top = s->top->next;
	//长度减1
	s->size--;
	return true;

}

void DisplayStack(Stack *s)
{
	LinkNode *tmp=s->top;
	int data;
	while(tmp!=NULL)
	{
		data = tmp->data;
		printf("%d ",data);
		tmp=tmp->next;
	}
	printf("\n");
}


void Stack_2_EnQueue(Stack *s1,Stack *s2,DataType data)
{	
	int tmp;
	while(!IsStackEmpty(s2))
	{
		pop(s2,&tmp);
		push(s1,tmp);
	}
	push(s1,data);
}
void Stack_2_DeQueue(Stack *s1,Stack *s2,DataType *data)
{
	int tmp;
	while(!IsStackEmpty(s1))
	{
		pop(s1,&tmp);
		push(s2,tmp);
	}
	pop(s2,data);
}
void QueueDisplay(Stack *s1,Stack *s2)
{
	if(IsStackEmpty(s1))
		DisplayStack(s2);
	else
		DisplayStack(s1);
}

int main(int argc, char const *argv[])
{
	Stack *s1=InitStack();
	Stack *s2=InitStack();

	int num;
	DataType data;
	int mem = 0;
	while(1)
	{
		scanf("%d", &num);
		if (num > 0)
		{
			mem++;
			Stack_2_EnQueue(s1,s2, num);
			QueueDisplay(s1,s2);
		}
		else
			if (num < 0)
			{
				mem--;
				Stack_2_DeQueue(s1,s2, &data);
				printf("出队:%d\n", data);
				QueueDisplay(s1,s2);
			}
			else
			{
				for (int i = 0; i < mem; ++i)
				{
					Stack_2_DeQueue(s1,s2, &data);
					printf("%d ", data);
				}
				mem = 0;
				printf("\n");			
			}
	}
	return 0;
}
2.用两个队列来实现一个栈

1.两个队列q1,q2
2.入栈:若找到空队列q1,入队,否则清空队列q1,将元素存到q2,再入队q1.
3.出栈:非空队列出队。

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

typedef int DataType;


//队列节点
typedef struct node
{
	DataType data;
	struct node *next;
}LinkNode;

//管理结构体
typedef struct
{
	struct node *front;		//队头指针
	struct node *rear;		//队尾指针
	unsigned int size;		//当前元素个数
}LinkQueue;


//初始化
LinkQueue *InitLinkQueue(void)
{
	LinkQueue *q=(LinkQueue *)malloc(sizeof(LinkQueue));
	if(q!=NULL)
	{
		q->front=NULL;
		q->rear=NULL;
		q->size=0;
		return q;
	}
	return q;
}

//判断队空
bool IsQueueEmpty(LinkQueue *q)
{
	return (q->size == 0);
}

LinkNode *CreatNode(DataType data)
{
	LinkNode * newNode = (LinkNode *)malloc(sizeof(LinkNode));
	if(newNode!=NULL)
	{
		newNode->data=data;
		newNode->next=NULL;
		return newNode;
	}
}

//入队
bool EnQueue(LinkQueue *q,LinkNode *newNode)
{
	if(newNode == NULL)
		return false;
	if(IsQueueEmpty(q))
	{
		//第一个数据进来,那么队头和队尾都指向这个节点
		q->front=newNode;
		q->rear=newNode;
	}
	else
	{
		//将新节点按照链表尾插的方式加入链表
		q->rear->next = newNode;
		//new就要作为队的新队尾节点
		q->rear = newNode;
	}
	q->size++;
	return true;
}


//出队
bool DeQueue(LinkQueue *q,LinkNode **nodeData)
{
	if(IsQueueEmpty(q))
		return false;

	//将队头的数据拿到
	*nodeData = q->front;
	//队头要重新变到下一个节点
	q->front=q->front->next;
	q->size--;
	return true;
}

bool DeQueue1(LinkQueue* q, DataType *data)
{
	//队列为空
	if (IsQueueEmpty(q))
	{
		return false;
	}

	if (q->size == 1)
	{
		q->rear = NULL;
	}

	//将队头的数据拿到
	*data = q->front->data;
	//队头要重新变到下一个节点
	q->front = q->front->next;
	q->size--;
	return true;
}


//遍历链表
void Display(LinkQueue *q)
{
	LinkNode *tmp=q->front;
	while(tmp != NULL)
	{
		printf("%d ",tmp->data);
		tmp=tmp->next;
	}
	printf("\n");
}


void Queue_2_Push(LinkQueue *q1,LinkQueue *q2,DataType data)
{
	LinkNode *tmp=NULL;
	if(IsQueueEmpty(q1))
	{
		EnQueue(q1,CreatNode(data));
		while(!IsQueueEmpty(q2))
		{
			DeQueue(q2,&tmp);
			EnQueue(q1,CreatNode(tmp->data));
		}
	}
	else
	{
		EnQueue(q2,CreatNode(data));
		while(!IsQueueEmpty(q1))
		{
			DeQueue(q1,&tmp);
			EnQueue(q2,CreatNode(tmp->data));
		}
	}

}
void Queue_2_Pop(LinkQueue *q1,LinkQueue *q2,DataType *data)
{
	LinkNode *tmp=NULL;
	if(!IsQueueEmpty(q1))
	{
		DeQueue(q1,&tmp);
	}
	else
	{
		DeQueue(q2,&tmp);
	}
	*data=tmp->data;

}

void DisplayStack(LinkQueue *q1,LinkQueue *q2)
{
	if(IsQueueEmpty(q1))
		Display(q2);
	else
		Display(q1);
}



int main(int argc, char const *argv[])
{
	LinkQueue *q1 = InitLinkQueue();
	LinkQueue *q2 = InitLinkQueue();



	int num;
	DataType data;
	int mem = 0;
	while(1)
	{
		scanf("%d", &num);
		if (num > 0)
		{
			mem++;
			Queue_2_Push(q1,q2, num);
			DisplayStack(q1,q2);
		}
		else
			if (num < 0)
			{
				mem--;
				Queue_2_Pop(q1,q2, &data);
				printf("出栈:%d\n", data);
				DisplayStack(q1,q2);
			}
			else
			{
				for (int i = 0; i < mem; ++i)
				{
					Queue_2_Pop(q1,q2, &data);
					printf("%d ", data);
				}
				mem = 0;
				printf("\n");			
			}
	}

	return 0;
}
3.球钟问题

球钟问题描述:球钟是一个利用球的移动来记录时间的简单装置。它有三个可以容纳若干个球的指示器:分钟指示器,五分钟指示器,小时指示器。若分钟指示器中有2个球,5分钟指示器中有6个球,小时指示器中有5个球,则时间为5:32。

在这里插入图片描述

​ 工作原理:每过一分钟,球钟就会从球队列的队首取出一个球放入分钟指示器,分钟指示器最多可容纳4个球。当放入第五个球时,在分钟指示器的4个球就会按照他们被放入时的相反顺序加入球队列的队尾。而第五个球就会进入分钟指示器。按此类推,五分钟指示器最多可放11个球,小时指示器最多可放11个球。当小时指示器放入第12个球时,原来的11个球按照他们被放入时的相反顺序加入球队列的队尾,然后第12个球也回到队尾。这时,三个指示器均为空,回到初始状态,从而形成一个循环。因此,该秋种表示的时间范围是从00:00到11:59

要想表示00:00到12:00需要多少个球?假设,指示器都为空,球队列需要多长时间能回到原来的状态?

1.定义1个队列q,3个栈s1,s5,s60
2.s1存4个元素判断栈满然后入栈s5,将s1所有元素出栈,入队q
3.s5存11个元素判断栈满然后入栈s60,将s5所有元素出栈,入队q
4.s60存11个元素判断栈满,将s60所有元素出栈,入队q
5.判断q中的元素顺序

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <time.h>

typedef int DataType;

//数据节点结构体
typedef struct node
{
	DataType data;		//数据
	struct node *next;	//指针
}LinkNode;


//管理结构体
typedef struct queue
{
	struct node *front;		//队头指针
	struct node *rear;		//队尾指针
	unsigned int size;		//当前元素个数
}LinkQueue;


//管理结构体
typedef struct stack
{
	struct node *top;		//栈顶偏移 栈顶指针就是节点指针的类型
	int size;				//当前元素个数
}Stack;


//初始化
LinkQueue *InitLinkQueue(void)
{
	LinkQueue *q=(LinkQueue *)malloc(sizeof(LinkQueue));
	if(q!=NULL)
	{
		q->front=NULL;
		q->rear=NULL;
		q->size=0;
		return q;
	}
	return q;
}

//判断队空
bool IsQueueEmpty(LinkQueue *q)
{
	return (q->size == 0);
}

LinkNode *CreatNode(DataType data)
{
	LinkNode * newNode = (LinkNode *)malloc(sizeof(LinkNode));
	if(newNode!=NULL)
	{
		newNode->data=data;
		newNode->next=NULL;
		return newNode;
	}
}

//入队
bool EnQueue(LinkQueue *q,LinkNode *newNode)
{
	if(newNode == NULL)
		return false;
	if(IsQueueEmpty(q))
	{
		//第一个数据进来,那么队头和队尾都指向这个节点
		q->front=newNode;
		q->rear=newNode;
	}
	else
	{
		//将新节点按照链表尾插的方式加入链表
		q->rear->next = newNode;
		//new就要作为队的新队尾节点
		q->rear = newNode;
	}
	q->size++;
	return true;
}


//出队
bool DeQueue(LinkQueue *q,LinkNode **nodeData)
{
	if(IsQueueEmpty(q))
		return false;

	//将队头的数据拿到
	*nodeData = q->front;
	//队头要重新变到下一个节点
	q->front=q->front->next;
	q->size--;
	return true;
}

bool DeQueue1(LinkQueue* q, DataType *data)
{
	//队列为空
	if (IsQueueEmpty(q))
	{
		return false;
	}

	if (q->size == 1)
	{
		q->rear = NULL;
	}

	//将队头的数据拿到
	*data = q->front->data;
	//队头要重新变到下一个节点
	q->front = q->front->next;
	q->size--;
	return true;
}


//遍历链表
void DisplayQueue(LinkQueue *q)
{
	int flag=0;
	LinkNode *tmp=q->front;
	while(tmp != NULL)
	{
		printf("%s%d",flag == 0?"":"-",tmp->data);
		flag=1;
		tmp=tmp->next;
	}
	printf("\n");
}


Stack * InitStack()
{
	Stack * s = malloc(sizeof(Stack));
	if(s!=NULL)
	{
		s->top=NULL;
		s->size=0;
		return s;
	}
}

bool IsStackEmpty(Stack *s)
{
	return (s->size == 0);
}

bool push(Stack *s,DataType data)
{
	LinkNode *newNode = malloc(sizeof(LinkNode));
	if(newNode!=NULL)
	{
		//新节点初始化
		newNode->data = data;
		//新节点next指向原来栈顶
		newNode->next = s->top;
		//将栈顶设置为新节点
		s->top=newNode;
		//元素个数加1
		s->size++;
		return true;
	}
	return false;
}


bool pop(Stack *s,DataType *data)
{
	if(IsStackEmpty(s)||s==NULL)
	{
		return false;
	}
	//取出数据
	*data = s->top->data;
	//栈顶偏移指向上一个节点
	s->top = s->top->next;
	s->size--;
	return true;

}

void DisplayStack(Stack *s)
{
	LinkNode *tmp=s->top;
	int data;
	while(tmp!=NULL)
	{
		data = tmp->data;
		printf("%d ",data);
		tmp=tmp->next;
	}
	printf("\n");
}

void Stack_pop_Enque(Stack *s,LinkQueue *q)
{
	int data;
	while(!IsStackEmpty(s))
	{
		pop(s,&data);
		EnQueue(q,CreatNode(data));
	}
}
bool CheckQueue(LinkQueue *q)
{
	if(IsQueueEmpty(q))
		return false;
	LinkNode *p=q->front;
	while(p->next!=NULL)
	{
		if(p->data > p->next->data)
		{
			return false;
		}
		p = p->next;
	}
	return true;
}

void show(Stack *s1,Stack *s5,Stack *s60,LinkQueue *q)
{
	system("clear");
	printf("s1\ts5\ts60\n");
	LinkNode *tmp1=s1->top;
	LinkNode *tmp5=s5->top;
	LinkNode *tmp60=s60->top;
	for(int i=1;i<12;i++)
	{
		if (tmp1!=NULL)
		{
			printf("%d", tmp1->data);
			tmp1=tmp1->next;
		}
		printf("\t");
		if (tmp5!=NULL)
		{
			printf("%d", tmp5->data);
			tmp5=tmp5->next;
		}
		printf("\t");
		if (tmp60!=NULL)
		{
			printf("%d", tmp60->data);
			tmp60=tmp60->next;
		}
		printf("\n");
	}
	DisplayQueue(q);
}

int main(int argc, char const *argv[])
{
	int tmp;
	int balls=27,i;
	int minutes=0;
	LinkQueue *q;
	Stack *s1,*s5,*s60;

	q = InitLinkQueue();
	s1 = InitStack();
	s5  = InitStack();
	s60 = InitStack();

	for(i=1;i<=balls;i++)
		EnQueue(q,CreatNode(i));
	
	// printf("%d",q->size);

	while(1)
	{
		show(s1,s5,s60,q);
		DeQueue1(q,&tmp);//出队一个球
		minutes++;
		usleep(1000*200);

		if(s1->size != 4) //栈没满,往里面放球
		{
			push(s1,tmp);
		}
		else
		{
			Stack_pop_Enque(s1,q);//球出栈入队
			if(s5->size!= 11)//栈没满,往里面放球
			{
				push(s5,tmp);
			}
			else
			{
				Stack_pop_Enque(s5,q);//球出栈入队
				if(s60->size!=11)
				{
					push(s60,tmp);
				}
				else
				{
					Stack_pop_Enque(s60,q);//球出栈入队
					EnQueue(q,CreatNode(tmp));//球入队
					if(CheckQueue(q))//球的顺序又变为了从小到大的顺序之后
						break;
				}
			}
		}			
		
	}
		
	printf("%d\n",minutes);
	


	return 0;
}

在这里插入图片描述
33120

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Yengi

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

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

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

打赏作者

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

抵扣说明:

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

余额充值