算法总结 栈+队列(c语言实现)

栈+队列

还是一道题

  • 两个人交替出牌。出牌时,如果某人打出的牌与桌上某张牌的牌面相同,即可将两张相同的牌及其中间所夹的牌全部取走,并依次放到自己手中牌的末尾。当任意一人 手中的牌全部出完时,游戏结束,对手获胜。

  • 两个人可以当成两个队列,出牌是出队,赢牌是入队。而桌面则可当成栈,有牌则top++,人拿回牌则top–;

  • 首先创建结构体实现队和栈

typedef struct node1 {//实现队列
   int data[1000];
   int head;
   int tail;
}D;

typedef struct node2 {实现栈
   int data[10];
   int top;
}Z;
  • 定义d1 , d2 来表示两个人,定义z来表示桌面
   D d1,d2;
   Z z;
  • 初始化队列和栈
//初始化队列d1和d2,此时两人手中没有牌 
   d1.head = 0; d1.tail = 0;
   d2.head = 0; d2.tail = 0;
   //初始化栈z为空,最开始桌面上也没有牌 
   z.top = 0;
  • 接下来从键盘分别读取6个数来表示两个人的手牌。
//读入d1手牌
   for(int i=0;i<6;i++){
   	scanf("%d",&d1.data[d1.tail]);
   	d1.tail++;
   } 
   //读入d2手牌 
   for(int j=0;j<6;j++){
   	scanf("%d",&d2.data[d2.tail]);
   	d2.tail++;
   } 
  • 有了牌,就可以打牌了,首先出牌,每次出牌都得放到桌面,然后与桌面其它牌比较,判断是否与之前的牌是否相同,即是否可以赢牌。可以使用枚举,与每张牌比较。但是再桶排序里有一个很好的算法。就是使用数组book[t];来标记是否有t 有的话 == 1,不过得先初始化book数组,置0;
	t = d1.data[d1.head];
   
   	if(book[t] == 0){//如果桌面上没有 t牌 ,则执行 
   		d1.head++;//d1的牌已经打到桌面,把打出的牌出队
   		z.top++;
   		z.data[z.top] = t;//再把打出的牌入栈 
   		book[t] = 1;//标记桌面上已经有了t牌 
   	}
   	else{
   		
   		d1.head++;//d1的牌已经打到桌面,把打出的牌出队
   		d1.data[d1.tail] = t;//把打到桌面的牌,放到队尾,即入队
   		d1.tail++;//更新队尾位置 
   		while(z.data[z.top] != t){//循环将栈中两数之间的所有数依次放到队尾 
   		
   			book[z.data[z.top]] = 0;//取消标记 
   			d1.data[d1.tail] = z.data[z.top];//从栈首依次将数放到队尾,出栈,入队
   			d1.tail++;//更新队尾位置
   			z.top--;//每次出栈会少一个数,即得更新栈首位置 	
   		} 
   		//将相同的两个数的另外一个出栈入对 
   		d1.data[d1.tail] = z.data[z.top];
   		d1.tail++;//更新队尾位置
   		book[z.data[z.top]] = 0;
   		z.top--;
   		
   	} 
  • 主要代码就是上面的了,下面是完整代码
#include 

typedef struct node1 {
   int data[1000];
   int head;
   int tail;
}D;

typedef struct node2 {
   int data[10];
   int top;
}Z;

/*
   让两个队列来模拟人,一个栈来模拟桌面 
*/ 
main(){
   D d1,d2;
   Z z;
   int t , book[10] = {0}; 
   //初始化队列d1和d2,此时两人手中没有牌 
   d1.head = 0; d1.tail = 0;
   d2.head = 0; d2.tail = 0;
   //初始化栈z为空,最开始桌面上也没有牌 
   z.top = 0;
   
   //读入d1手牌
   for(int i=0;i<6;i++){
   	scanf("%d",&d1.data[d1.tail]);
   	d1.tail++;
   } 
   //读入d2手牌 
   for(int j=0;j<6;j++){
   	scanf("%d",&d2.data[d2.tail]);
   	d2.tail++;
   } 
   
   while(d1.head < d1.tail && d2.head <d2.tail){
   	//开始游戏
   	t = d1.data[d1.head];
   
   	if(book[t] == 0){//如果桌面上没有 t牌 ,则执行 
   		d1.head++;//d1的牌已经打到桌面,把打出的牌出队
   		z.top++;
   		z.data[z.top] = t;//再把打出的牌入栈 
   		book[t] = 1;//标记桌面上已经有了t牌 
   	}
   	else{
   		
   		d1.head++;//d1的牌已经打到桌面,把打出的牌出队
   		d1.data[d1.tail] = t;//把打到桌面的牌,放到队尾,即入队
   		d1.tail++;//更新队尾位置 
   		while(z.data[z.top] != t){//循环将栈中两数之间的所有数依次放到队尾 
   		
   			book[z.data[z.top]] = 0;//取消标记 
   			d1.data[d1.tail] = z.data[z.top];//从栈首依次将数放到队尾,出栈,入队
   			d1.tail++;//更新队尾位置
   			z.top--;//每次出栈会少一个数,即得更新栈首位置 	
   		} 
   		//将相同的两个数的另外一个出栈入对 
   		d1.data[d1.tail] = z.data[z.top];
   		d1.tail++;//更新队尾位置
   		book[z.data[z.top]] = 0;
   		z.top--;
   		
   	} 
   
   	t = d2.data[d2.head];//d2出牌 
   
   	if(book[t] == 0){//如果桌面上没有 t牌 ,则执行 
   		d2.head++;//d2的牌已经打到桌面,把打出的牌出队
   		z.top++;
   		z.data[z.top] = t;//再把打出的牌入栈 
   		book[t] = 1;//标记桌面上已经有了t牌 
   	}
   	else{
   		
   		d2.head++;//d2的牌已经打到桌面,把打出的牌出队
   		d2.data[d2.tail] = t;//把打到桌面的牌,放到队尾,即入队
   		d2.tail++;//更新队尾位置 
   		while(z.data[z.top] != t){//循环将栈中两数之间的所有数依次放到队尾 
   		
   			book[z.data[z.top]] = 0;//取消标记 
   			d2.data[d2.tail] = z.data[z.top];//从栈首依次将数放到队尾,出栈,入队
   			d2.tail++;//更新队尾位置
   			z.top--;//每次出栈会少一个数,即得更新栈首位置 
   			
   		} 
   		//将相同的两个数的另外一个出栈入对 
   		d2.data[d2.tail] = z.data[z.top];
   		d2.tail++;//更新队尾位置
   		book[z.data[z.top]] = 0;
   		z.top--;
   		
   	} 		
   }
   
   if(d2.head == d2.tail){
   	printf("d1获胜\n");
   	printf("d1当前手牌为:");
   	for(int i=d1.head;i<d1.tail;i++){
   		printf("%d ",d1.data[i]);
   	} 
   	if(z.top>0){
   		printf("\n桌上的牌为:");
   		for(int j=1;j<=z.top;j++){
   			printf("%d ",z.data[j]);
   		} 
   	}
   	else{
   		printf("\n桌上没有牌"); 
   	}
   } 
   else{
   	printf("d2获胜\n");
   	printf("d2当前手牌为:");
   	for(int i=d2.head;i<d2.tail;i++){
   		printf("%d ",d2.data[i]);
   	} 
   	if(z.top>0){
   		printf("\n桌上的牌为:");
   		for(int j=1;j<=z.top;j++){
   			printf("%d ",z.data[j]);
   		} 
   	}
   	else{
   		printf("\n桌上没有牌"); 
   	}
   }
} 

使用dev是可以实现的
测试用例:

2 4 1 2 5 6 
3 1 3 5 6 4 
d2获胜
d2当前手牌为:6 5 2 3 4 1
桌上的牌为:3 4 5 6 2 1

书上说上面的代码还不完善,一些特殊测试数据会没有结果,一直循环下去。就是说现在的程序不怎么"健壮"。
2020/3/25/22/45

你可能感兴趣的:(算法总结)