向量容器2

题3:

以下代码有什么问题?如何修改?【中国某著名综合软件公司2005年面试题】

 

// P96_example3.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include <vector>

void print(std::vector<int>);


int _tmain(int argc, _TCHAR* argv[])
{
	std::vector<int> vec;
	vec.push_back(1);
	vec.push_back(6);
	vec.push_back(6);
	vec.push_back(3);
	//删除vec数组中的所有6
	std::vector<int>::iterator itor1;
	std::vector<int>::iterator itor2;
	for(itor1 = vec.begin(); itor1 != vec.end(); itor1++)
	{
		if(6 == *itor1)
		{
			itor2 = itor1;
			vec.erase(itor2);	//删除指定位置的元素
		}
	}
	print(vec);
	return 0;
}

void print(std::vector<int> v)
{
	std::cout<<"vector size is: "<<v.size()<<std::endl;
	std::vector<int>::iterator p = v.begin();
	while(p != v.end())
	{
		std::cout<<*p<<std::endl;
		p++;
	}
}


解析:

 

这是迭代器问题,只能删除第一个6,以后迭代器就失效了,不能删除之后的元素。

itor2 = itor1;这句说明两个迭代器是一样的。vec.erase(itor2);等于vec.erase(itor1);,这时指针已经指向下一个元素了。itor1++;又自增了,指向了下一个元素3,略过了第二个6。

答案:

修改方法1:使用vector模版里面的remove函数进行修改,代码如下:

 

// P96_example3.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include <vector>
#include <algorithm>


void print(std::vector<int>);


int _tmain(int argc, _TCHAR* argv[])
{
	std::vector<int> vec;
	vec.push_back(1);
	vec.push_back(6);
	vec.push_back(6);
	vec.push_back(3);
	//删除vec数组中的所有6
	std::vector<int>::iterator itor1;
	std::vector<int>::iterator itor2;
	itor1 = vec.begin();
	vec.erase(std::remove(vec.begin(),vec.end(),6),vec.end());
	print(vec);
	return 0;
}

void print(std::vector<int> v)
{
	std::cout<<"vector size is: "<<v.size()<<std::endl;
	std::vector<int>::iterator p = v.begin();
	while(p != v.end())
	{
		std::cout<<*p<<std::endl;
		p++;
	}
}

修改方法2:为了让其不略过第二个6,可以使itor1--,再回到原来的位置上。具体代码修改如下:

 

 

// P96_example3.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include <vector>


void print(std::vector<int>);


int _tmain(int argc, _TCHAR* argv[])
{
	std::vector<int> vec;
	vec.push_back(1);
	vec.push_back(6);
	vec.push_back(6);
	vec.push_back(3);
	//删除vec数组中的所有6
	std::vector<int>::iterator itor1;
	std::vector<int>::iterator itor2;
	itor1 = vec.begin();
	for(itor1 = vec.begin(); itor1 != vec.end(); itor1++)
	{
		if(6 == *itor1)
		{
			itor2 = itor1;
			vec.erase(itor2);	//删除指定位置的元素
			itor1--;
		}
	}
	print(vec);
	return 0;
}

void print(std::vector<int> v)
{
	std::cout<<"vector size is: "<<v.size()<<std::endl;
	std::vector<int>::iterator p = v.begin();
	while(p != v.end())
	{
		std::cout<<*p<<std::endl;
		p++;
	}
}



 

 

转载于:https://www.cnblogs.com/snake-hand/p/3167821.html

<think>嗯,用户现在想了解C++STL中队列和向量容器的区别。这是个关于容器选择的实用问题。可能用户在实际编程中遇到了两种容器的使用场景混淆,或者在学习数据结构时想区分它们的特性。观察用户提供的站内引用材料,这些引用覆盖了指针管理、智能指针、编译链接和C++类型系统等知识。其中引用[1]关于delete操作符的示例显示出用户对容器内存管理的兴趣,引用[2]比较unique_ptr和auto_ptr说明用户可能关注资源所有权问题。不过用户当前问题集中在queue和vector这两个具体容器上。根据知识库总结:1.vector是顺序容器,底层是动态数组,支持随机访问(O(1)复杂度)和尾部高效操作2.queue是容器适配器,通常基于deque实现,只暴露队首队尾操作,遵循FIFO规则差异关键点在访问权限、内部结构和接口限制特别是vector的随机访问特性(operator[]/at())和queue的访问限制(只能访问队首队尾)需要强调使用场景差异:科学计算需要随机访问选vector任务调度需要FIFO选queue准备用表格对比会清晰一些此外用户引用的CMake配置示例表明可能在实际项目中使用这些容器,最后可以提醒链接库等注意事项需要自然地融合[^1]关于容器元素内存管理的引用,避免直接提到但说明queue适配器特性时暗示所有权转移可以在最后的问题中引入deque与queue的关系,与引用[2]的智能指针所有权转移概念形成呼应</think> ### C++ STL `queue` 与 `vector` 的区别 以下是两者的核心差异: | **特性** | **`std::queue`** | **`std::vector`** | |-------------------|---------------------------------------------|--------------------------------------------| | **本质** | 容器适配器(封装 deque/list) | 顺序容器(动态数组) | | **访问规则** | 先进先出(FIFO) | 随机访问(任意位置) | | **元素访问** | 仅限队首(`front()`)和队尾(`back()`) | 支持下标(`[]`)、`at()`、迭代器访问 | | **插入/删除操作**| `push()`(队尾插入)、`pop()`(队首删除) | `push_back()`/`pop_back()`、任意位置插入删除 | | **底层实现** | 默认基于 `deque`(可指定为 `list`) | 动态数组,内存连续 | | **迭代器** | **不提供迭代器** | 提供随机访问迭代器 | | **复杂度** | 插入/删除:$O(1)$ | 尾部操作:$O(1)$;中间操作:$O(n)$ | | **典型用途** | 任务调度、BFS算法 | 随机访问、动态数组需求 | --- ### 详细说明: 1. **设计目的不同** - `queue` 是 **受限序列**:强制遵循 FIFO 规则,仅允许队尾插入和队首删除。 - `vector` 是 **通用动态数组**:支持任意位置的操作(尽管中间操作成本高)。 2. **内存结构** - `vector`:元素在**连续内存**中存储,支持指针算术运算(例如 `&vec[0] + 5`)。 - `queue`:依赖底层容器(如 `deque`),内存**不一定连续**。 3. **接口差异** - `queue` 仅提供: ```cpp push(element) // 入队 pop() // 出队(无返回值) front() // 访问队首 back() // 访问队尾 ``` - `vector` 提供完整序列操作: ```cpp push_back(element), pop_back() insert(iterator, element), erase(iterator) operator[], at(), data() ``` 4. **性能对比** - `vector` 随机访问复杂度为 $O(1)$,但中间插入/删除为 $O(n)$。 - `queue` 所有操作严格 $O(1)$(依赖底层容器的稳定性能)。 5. **底层容器灵活性** - `queue` 可指定底层容器(默认为 `deque`): ```cpp std::queue<int, std::list<int>> list_queue; // 基于 list 实现 ``` - `vector` 无此适配器特性。 --- ### 使用场景建议 - **选择 `queue` 时**: - 需要严格 FIFO 行为(如消息队列)。 - 避免意外修改中间数据(例如 `queue` 不提供 `insert()`)。 - **选择 `vector` 时**: - 需要快速随机访问(如 `vec[i]`)。 - 需要动态数组且尾部操作频繁。 - 需与其他算法配合(如排序 `std::sort(vec.begin(), vec.end())`)。 > ⚠️ **注意**:若 `vector` 存储指针,需手动释放内存(见引用[^1]),而 `queue` 作为适配器,其内存管理由底层容器负责。 --- ### 代码示例 **`queue` 的 FIFO 操作**: ```cpp #include <queue> std::queue<int> q; q.push(1); // 队列: [1] q.push(2); // 队列: [1, 2] int a = q.front(); // a=1 q.pop(); // 队列: [2] ``` **`vector` 的随机访问**: ```cpp #include <vector> std::vector<int> v = {3, 1, 4}; v[1] = 0; // 修改第二个元素: [3, 0, 4] v.insert(v.begin()+1, 9); // 插入元素: [3, 9, 0, 4] ``` --- ### 相关问题 1. 为什么 `queue` 默认基于 `deque` 而不是 `vector` 实现? 2. `vector::insert()` 和 `vector::push_back()` 的性能差异如何优化? 3. 什么场景下应优先选择 `deque` 而非 `vector` 或 `queue`? 4. 如何实现一个基于数组的循环队列(Circular Queue)? [^1]: `queue` 作为容器适配器,不直接管理内存;其元素的生命周期由底层容器(如 `deque`)控制。 [^2]: C++11 引入的 `unique_ptr` 等智能指针可优化资源管理(对比废弃的 `auto_ptr`)。 [^3]: 链接库时需确保头文件路径(`include_directories`)和库路径(`link_directories`)正确配置。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值