【摸鱼】栈

上一篇讲的是队列,是一种先进先出的数据结构。还有一种后进先出的数据结构,称为栈。

栈限定为只能在一端进行插入和删除操作。比如往杯子里面放球,然后再往出拿,显然,最后放入的球可以最先拿出来。

判断回文

通过栈这个数据结构可以判断一个字符是否是回文。

  • 读取字符串
char a[101];
int len;
gets(a);
len=strlen(a);
  • 如果一个字符串是回文的话,那么它必须是中心对称,求中点
mid=len/2-1;
  • 将mid之前的字符全部入栈,此处栈用来存储字符,所以此处用来实现栈的数组类型是字符数组,char s[101];,
  • 初始化栈,top=0
  • 入栈的操作top++;s[top]=x;(假设需要入栈的字符暂存在字符变量x中),简写成s[++top]=x;
  • 代码实现mid之前字符全部入栈
for(i=0;i<=mid;i++)
{
s[++top]=a[i];
}
  • 判断回文,将当前栈中的字符依次出栈,看是否能与mid之后的字符一一匹配,如果能匹配就是回文串,否则不是。
for(i=mid+1;i<=len-1;i++)
{
if(a[i]!=s[top])
{
break;
}
top--;
}
if(top==0)
printf("YES");
else
printf("NO");

当top=0时,说明栈内所有的字符都被一一匹配了,那么这个字符就是回文串。

下面附判断回文串完整代码:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//解密回文--栈
int main()
{
	char a[101],s[101];
	int i,len,mid,next,top;
	gets(a);//读入字符串
	len=strlen(a);//字符串长度
	mid=len/2-1;//求字符串中点
	top=0;//初始化栈
	//将mid前的字符依次入栈
	for(i=0;i<=mid;i++)
	s[++top]=a[i];
	
	//判断字符串长度是奇数还是偶数,并找出需要进行字符匹配的起始下标
	if(len%2==0) //偶数 
	next=mid+1;
	else //奇数 
	next=mid+2;
	//开始匹配
	for(i=next;i<=len-1;i++)
	{
		if(a[i]!=s[top])
			break;
			top--;	
	 }
	 //当top=0时,说明栈内所有的字符都被一一匹配了
	 if(top==0)
	 printf("YES\n");
	 else
	 printf("NO\n");
	 return 0; 
 } 

栈还可以用来进行验证括号的匹配。

纸牌游戏——小猫钓鱼

游戏规则:将一副扑克牌平均分成两份,每人拿1份,小哼先拿出第一张扑克牌放在桌上,然后小哈也拿出手中的第一张扑克牌,并放在小哼刚打出的扑克牌上面,两人交替出牌,出牌时,如果某人打出的牌和桌上某张牌牌面相同,即可将两张相同的牌,及夹在其中间的牌全部拿走,并依次放在自己手中牌的末尾,当任意一个人手中的牌全部出完时,游戏结束,对手获胜。
游戏开始时,小哼手中6张牌2,4,1,2,5,6。小哈手上也有6张牌3,1,3,5,6,4。牌面只有1~9。判断是谁赢。

分析

对于玩家而言有2种操作:赢牌和出牌

  • 赢牌:入队
  • 出牌:出队

对于桌子而言有2种操作:牌被放到桌上和牌被从桌上拿走

  • 牌放到桌子上:入栈
  • 牌被拿走:出栈

两个玩家,一张桌子,所以用两个队列,一个栈来模拟整个游戏。

完整代码

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct queue
{
	int data[1000];
	int head;
	int tail;
 };
 struct stack
 {
 	int data[10];
 	int top;
 };
 int main()
 {
 	struct queue q1,q2;//小哼的扑克牌队列q1,小哈的扑克牌队列q2
	 struct stack s;//桌子上的扑克牌
	 int book[10];
	 int i,t;
	 //初始化队列,q1,q2为空,两人手中没有牌 
	 q1.head=1;
	 q1.tail=1;
	 q2.head=1;
	 q2.tail=1;
	 //初始化栈,桌子上面没有牌 
	 s.top=0;
	 //初始化用来标记的数组,用来标记哪些牌已经在桌子上
	 //book[10]={0};不可取 
	 for(i=0;i<=9;i++)
	 {
	 	book[i]=0;//初始化	  
	  } 
	  //依次向队列中插入6个数
	  //小哼手上有6张牌
	  for(i=1;i<=6;i++) 
	  {
	  	scanf("%d",&q1.data[q1.tail]);//读入一个数到队尾q1.data[1],q1.data[2]...
	  	q1.tail++;//队尾往后挪一位,q1.tail=2,3... 
	  	
	   } 
	   //小哈手上有6张牌
	   for(i=1;i<=6;i++)
	   {
	   	scanf("%d",&q2.data[q2.tail]);
	   	q2.tail++;
			  }	
		//当队列不为空时,执行循环
		while(q1.head<q1.tail&&q2.head<q2.tail)
		{
			t=q1.data[q1.head];//小哼出一张牌,q1.data[1]
			//判断小哼当前打出的牌是否能赢牌
			if(book[t]==0)//如果桌面上没有为t的牌
			{
				//桌面上没有为t的牌,说明小哼此轮没有赢牌
				q1.head++;//小哼打出一张牌,那么这张牌就出列
				s.top++;//桌面上多出一张牌,s.top=1
				s.data[s.top]=t;//s.data[1]=t,将小哼打出的一张牌放到桌上,入栈
				book[t]=1;//标记桌面上此时已有牌面为t的牌 
			 } 
			 else
			 {
			 	//小哼此轮可以赢0
				 q1.head++;//小哼已经打出一张牌,此时将那一张牌出列
				 q1.data[q1.tail]=t;//因为可以赢牌,所以将打出的牌放到手中牌的末尾
				 q1.tail++;
				 while(s.data[s.top]!=t)//把桌上赢的牌(从当前桌面最顶部一张牌开始取,直至取到的牌与打出的牌相同为止)依次放到手中牌的末尾
				 {
				 	book[s.data[s.top]]=0;//取消标记,将桌上的牌取消标记 
					 q1.data[q1.tail]=s.data[s.top];//依次放入队尾
					 q1.tail++;
					 s.top--;//栈中少了一张牌,所以栈顶减1 
				  } 
				  //收回桌面上牌面为t的牌
				  book[s.data[s.top]]=0;
				  q1.data[q1.tail]=s.data[s.top];
				  q1.tail++;
				  s.top--;
				  
			  } 
			  if(q1.head==q1.tail)
			  break;//如果小哼手上牌打完,那么停止游戏 
			  t=q2.data[q2.head];//小哈打出一张牌
			  if(book[t]==0)
			  {
			  	q2.head++;
			  	s.top++;
			  	s.data[s.top]=t;
			  	book[t]=1;
			  	
			   }
			   else
			   {
			   	q2.head++;
			   	q2.data[q2.tail]=t;
			   	q2.tail++;
			   	while(s.data[s.top]!=t)
			   	{
			   		book[s.data[s.top]]=0;
			   		q2.data[q2.tail]=s.data[s.top];
			   		q2.tail++;
			   		s.top--;
				   }
				   book[s.data[s.top]]=0;
				   q2.data[q2.tail]=s.data[s.top];
				   q2.tail++;
				   s.top--;
				} 
		   } 
		   if(q2.head==q2.tail)
		   {
		   	printf("小哼win\n");
		   	printf("小哼当前手中的牌是");
			   for(i=q1.head;i<=q1.tail-1;i++)
			   printf(" %d",q1.data[i]);
			   if(s.top>0)
			   {
			   	printf("\n桌上的牌是");
			   	for(i=1;i<=s.top;i++)
			   	printf(" %d",s.data[i]);
				}
				else
				printf("\n桌上已经没有牌了");
			 }
			 else
			 {
			 	printf("小哈win\n");
			 	printf("小哈当前手中的牌是");
				 for(i=q2.head;i<=q2.tail-1;i++)
				 printf(" %d",q2.data[i]);
				 if(s.top>0)
				 {
				 	printf("\n桌上的牌是");
				 	for(i=1;i<=s.top;i++)
				 	printf(" %d",s.data[i]);
				 }
				 else
				 printf("\n桌面上已经没有牌了");
			  } 
			  getchar();getchar();
			  return 0;
 }
 

。。。好长的难代码,自己一下子写也写不出来,这就是就是计算机模拟过程,之前涉足数模的时候,老师说要给一个模型就能用程序写出来,我说我不能。。一个软工的学生,多多少少得学点编程到时候还能混口饭的。。虽然数模是个水比赛,代码大部分也是copy,,,但是我发现了计算机模拟过程是我一点都不会的。。。
在这里插入图片描述
结束

分割线

=============================================================
判断每个人打出一张牌之后能否赢牌,可以通过枚举桌上的每一张牌来实现,用for循环来依次判断桌上的每一张牌是否与打出的牌相等。
上述代码通过用一个数组来记录桌上有哪些牌
因为牌面只有1~9,所以开一个大小为10的数组来记录当前桌上已经有哪些牌面。
book[10]
没有赢牌时和赢牌时代码区别:
未赢牌时:

if(book[t]==0)
	{
		q.head++;//打出一张牌,所以将打出的牌出列
		s.top++;//桌面上多出一张牌
		s.data[s.top]=t;//s.top是指向栈顶的变量
	}

赢牌时:

//赢牌
else//book[t]==1
	{
		q.head++;//打出一张牌,将打出的牌出列
		q.data[q.tail]=t;//已经确定能赢牌,所以就将这张牌直接放到队尾,即放到自己手中牌的末尾
		q.tail++;
		while(s.data[s.top]!=t)//桌上和自己打的牌不一样的牌
		{
			book[s.data[s.top]]=0;//因为牌要取走,所以就取消标记
			q.data[q.tail]=s.data[s.top];//将桌上那些牌依次放入自己手中牌之后
			q.tail++;
			s.top--;//桌面上少了1张牌
		}
		//收回桌面上为t的牌
		book[s.data[s.top]]=0;//取消标记
		q.data[q.tail]=s.data[s.top];
		q.tail++;
		s.top--;
	}

再次回看题目,程序模拟过程对应实际游戏过程
* 出牌——>出队列
*桌面上多一张牌——>栈顶+1
*桌上少一张牌——>栈顶-1
*赢牌时,先将打出的牌立即放到自己手中牌的最后,然后将桌面上牌和自己手中不一样的收回手中,依次放到自己手中末尾
*最后再将桌上的和自己手中一样的牌收了,放入手中牌最后

=============================================================
真的结束,有补充再说吧

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值