队列、栈

1. 队列

队列是一种特殊的线性结构,它只允许在队列的首部进行删除操作,称为“出队”;而在队列的尾部进行插入操作,称为“入队”;当队列中没有元素,即head==tail的时候,称为空队列。

例题:解密一组数6 3 1 7 5 8 9 2 4,规则是将第一个数删除,第二个数放在队列末尾,再将第三个数删除,把第四个数放到队列末尾......直到剩下最后一个数,将最后一个数也删除。最后把删除的数连在一起,就是解密后的答案。

思路:引入两个变量head和tail,head用来记录队列的队首,即第一个数;tail用来记录最后一个数的下一个位置,即队尾的后一个数。

相应代码:

#include<iosream>
#include<cstdio>
using namespace std;

int main() {
	int q[101] = { 0,6,3,1,7,5,8,9,2,4 };
	int head = 1, tail = 10;//tail指向队尾的后一个位置
	while (head < tail) {//当队列不为空的时候执行循环
		printf("%d ", q[head]);
		head++;
		q[tail] = q[head];
		tail++;
		head++;
	}
	printf("\n");
	system("pause");
	return 0;
}

代码实现:


2. 栈

栈是一种后进先出的数据结构,其限定为只能在一端进行插入和删除。栈的实现不难,只需一个一维数组和一个指向栈顶的变量top就可以了,我们通过top来对栈进行插入和删除操作。

例题:判断是否为回文

思路:回文,如“12321”,“abcba”,“shhs”等。如果一个字符是回文的话,那么它必须是中间对称的,我们需要求中心点mid。先将mid之前的全部入栈,然后将当前栈中的字符依次出栈,看看能否与mid之后的字符一一匹配。最后如果top的值为0,就说明栈内所有的字符都被一一匹配了,该字符串为回文字符串。

相应代码:

#include<iostream>
#include<cstdio>
#include<string>
using namespace std;

int main() {
	char a[101], s[101];
	int top, next, mid, len;
	gets_s(a);
	len = strlen(a);
	mid = len / 2 - 1;
	top = 0;//栈的初始化
	for (int i = 0; i <= mid; i++) {
		s[++top] = a[i];//将mid前的字符依次入栈
	}
	if (len % 2 == 0)//偶数
		next = mid + 1;
	else
		next = mid + 2;
	for (int i = next; i <= len-1; i++) {//开始匹配
		if (a[i] != s[top])
			break;
		top--;
	}
	if (top == 0)//如果top的值为0,说明栈内所有的字符都被一一匹配了
		printf("Yes!");
	else
		printf("No!");
	printf("\n");
	system("pause");
	return 0;
}


综合问题:纸牌游戏

小哼和小哈在一起打牌,小哼先出牌,小哈后出牌。如果所出的牌与桌上有相同的,那么此次出牌的人依次倒着将两张相同的牌以及中间夹着的牌收走,放到自己手中的牌的最后。最后谁手中的牌先没了,谁就输了。

相应代码:

#include<iostream>
#include<cstdio>
using namespace std;

typedef struct queue {
	int data[1000];
	int head, tail;
}QUEUE;

typedef struct stack {
	int data[10];
	int top;
}STACK;

int main() {
	int book[10];
	int t;
	QUEUE q1, q2;
	STACK s;
	//初始化队列
	q1.head = 1; q1.tail = 1;
	q2.head = 1; q2.tail = 1;
	//初始化栈
	s.top = 0;
	//初始化用来标记的数组,用来标记那些牌已经在桌子上
	for (int i = 1; i <= 9; i++)
		book[i] = 0;

	//依次向队列插入6个数
	//小哼手上的6张牌
	for (int i = 1; i <= 6; i++) {
		scanf("%d", &q1.data[q1.tail]);
		q1.tail++;
	}
	//小哈手上的6张牌
	for (int 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];//小哼出一张牌
		//判断小哼当前打出的牌是否能赢
		if (book[t] == 0) {//表明桌上没有牌面为t的牌
			//小哼此轮没有赢牌
			q1.head++;//小哼已经打出一张牌,所以要将打出的牌出队
			s.top++;
			s.data[s.top] = t;//把打出的牌放到桌上,即入栈
			book[t] = 1;//标记桌上已经有牌面为t的牌
		}
		else {
			//小哼此轮可以赢牌
			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) {//表明桌上没有牌面为t的牌
			//小哈此轮没有赢牌
			q2.head++;//小哈已经打出一张牌,要把打出的牌出位
			s.top++;
			s.data[s.top] = t;//把打出的牌放到桌上,即入栈
			book[t] = 1;//标记桌上已经有牌面为t的牌
		}
		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--;
			}
			//收回桌上牌面为t的牌
			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 (int i = q1.head; i < q1.tail; i++)
			printf("%d ", q1.data[i]);
		if (s.top > 0) {//如果桌上有牌,则依次输出桌上的牌
			printf("\n桌上的牌是");
			for (int i = 1; i <= s.top; i++)
				printf("%d ", s.data[i]);
		}
		else
			printf("\n桌上已经没有牌了");
	}
	else {
		printf("小哈win\n");
		printf("小哈当前手中的牌是");
		for (int i = q2.head; i < q2.tail; i++)
			printf("%d ", q2.data[i]);
		if (s.top > 0) {//如果桌上有牌,则依次输出桌上的牌
			printf("\n桌上的牌是");
			for (int i = 1; i <= s.top; i++)
				printf("%d ", s.data[i]);
		}
		else
			printf("\n桌上已经没有牌了");
	}
	printf("\n");
	system("pause");
	return 0;
}

代码实现:



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值