队列、栈

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;
}

代码实现:



<think>我们被要求参考站内引用,这些引用提供了Python中队列的实现方法。用户想了解Python中队列的使用与实现。我们将结合引用内容进行回答,并确保回答结构清晰。 引用内容总结: - 引用[1]:提供了一个队列的实现,使用列表,实现了enqueue(入队)、dequeue(出队)、head(队首元素)、length(队列长度)等方法。 - 引用[2]:展示了使用两个来实现队列的方法,其中一个用于入队,另一个用于出队。 - 引用[3]:提供了一个的实现,使用列表,并实现了的基本操作(push, pop, peek, size, is_empty)以及测试用例。同时提到了队列的实现,但队列的实现部分未完整给出(只提到队列的实现,但代码是的)。 - 引用[4]:展示了队列的另一种实现,同样使用列表,并实现了插入元素、插入多个元素、移除元素(从队首)、大小、展示队列和判断是否为空的方法。 - 引用[5]:建议使用collections.deque来实现队列,因为它在两端都有快速的添加和删除操作。 根据以上引用,我们可以总结: 1. (Stack)的实现:通常使用列表(list)来实现,因为列表的append和pop方法可以很方便地实现的后进先出(LIFO)特性。 2. 队列(Queue)的实现:虽然可以用列表实现(如引用[1]和[4]),但是列表在头部pop(0)的操作时间复杂度为O(n),效率不高。因此,引用[5]建议使用collections.deque,它是双端队列,在两端添加或删除元素的时间复杂度都是O(1)。 另外,引用[2]提供了一种使用两个来实现队列的方法,这种方法虽然效率不如deque,但作为一种经典思路,也值得介绍。 因此,我们的回答将包括: 1. 的实现(使用列表)以及基本操作。 2. 队列的实现:两种方式(使用列表和collections.deque),并说明列表实现的效率问题,推荐使用deque。 3. 使用两个实现队列的方法(作为补充知识)。 同时,我们将按照要求生成相关问题。 注意:引用内容中,引用[3]提供的实际上是的完整实现,而队列部分只提到了但没有给出完整代码(在引用[3]中队列实现部分缺失),因此我们将参考其他引用来补充队列的实现。 回答结构: 1. 的实现与使用 2. 队列的实现与使用(包括列表实现和deque实现) 3. 补充:两个实现队列 4. 相关问题 </think>### Python中队列的使用与实现 #### 一、的实现与使用(后进先出/LIFO) 的常用操作包括`push`(入)、`pop`(出)、`peek`(查看顶)和`size`(获取大小)。Python列表天然支持操作: ```python class Stack: def __init__(self): self.items = [] def push(self, item): self.items.append(item) # 入操作 def pop(self): if not self.is_empty(): return self.items.pop() # 出操作(移除并返回末尾元素) def peek(self): if not self.is_empty(): return self.items[-1] # 查看顶元素 def size(self): return len(self.items) # 获取大小 def is_empty(self): return not bool(self.items) # 检查是否为空 # 使用示例 s = Stack() s.push(10) s.push(20) print(s.pop()) # 输出: 20 (最后入的元素最先出) ``` > **关键点**: > - Python列表的`append()`和`pop()`时间复杂度均为 $O(1)$,天然适合实现 > - 常用于函数调用、括号匹配、表达式求值等场景[^3] #### 二、队列的实现与使用(先进先出/FIFO) ##### 方法1:使用列表(适用于低频操作) ```python class ListQueue: def __init__(self): self.items = [] def enqueue(self, item): self.items.append(item) # 入队 def dequeue(self): if not self.is_empty(): return self.items.pop(0) # 出队(移除首元素) def is_empty(self): return len(self.items) == 0 # 注意:list.pop(0) 时间复杂度为 $O(n)$[^4] ``` ##### 方法2:推荐使用`collections.deque`(高效双端队列) ```python from collections import deque class EfficientQueue: def __init__(self): self.queue = deque() # 使用双端队列 def enqueue(self, item): self.queue.append(item) # 入队 def dequeue(self): if self.queue: return self.queue.popleft() # 出队(时间复杂度$O(1)$) def size(self): return len(self.queue) # 使用示例 q = EfficientQueue() q.enqueue("A") q.enqueue("B") print(q.dequeue()) # 输出: "A" (最先入队的元素最先出队) ``` > **关键点**: > - `deque.popleft()`时间复杂度为 $O(1)$,远优于列表的 $O(n)$[^5] > - 队列常用于任务调度、缓冲区管理、BFS算法等场景 #### 三、扩展实现:双模拟队列 ```python class StackQueue: def __init__(self): self.in_stack = [] # 输入 self.out_stack = [] # 输出 def push(self, item): self.in_stack.append(item) # 入队操作 def pop(self): if not self.out_stack: # 当输出为空时 while self.in_stack: # 将输入元素反转存入输出 self.out_stack.append(self.in_stack.pop()) if self.out_stack: return self.out_stack.pop() # 出队操作 # 时间复杂度:均摊$O(1)$[^2] ``` ### 性能对比 | 操作 | 列表 | 列表队列 | deque队列 | 双队列 | |-------------|--------|----------|-----------|----------| | **入队/入** | $O(1)$ | $O(1)$ | $O(1)$ | $O(1)$ | | **出队/出** | $O(1)$ | $O(n)$ | $O(1)$ | 均摊$O(1)$ | > **实践建议**: > - 场景:直接使用列表 > - 队列场景:优先选择`collections.deque` > - 特殊需求:双实现可解决某些特定约束问题
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值