C++ 这个向量以前发生过吗
我有很多向量(以10^4的顺序,甚至更多!),我将从流的输入中获得更多向量。比如说,我有C++ 这个向量以前发生过吗,c++,vector,stl,implementation,C++,Vector,Stl,Implementation,我有很多向量(以10^4的顺序,甚至更多!),我将从流的输入中获得更多向量。比如说,我有 v1=10411 v2=1125362 v3=01150 我有10^4个这样的向量 现在,我输入一个向量,我想检查它以前是否出现过,你建议我怎么做 我将列出我想到的技术,以及伴随这些技术而来的错误: 使用std::map,或std::set。但是,std::map std::set不支持向量作为参数 要将向量中的每个整数转换为字符串类型,请按顺序追加它们并将字符串存储在映射中。错误:v5=11 1和v
v1=10411
v2=1125362
v3=01150
- 使用
,或std::map
。但是,std::set
不支持向量作为参数std::map std::set
- 要将向量中的每个整数转换为字符串类型,请按顺序追加它们并将字符串存储在映射中。错误:
和v5=11 1
的情况将显示为相同v6=1 1
- 与上面类似,只是在每个整数后添加一个分隔符。错误:太单调而无法编码
对于10^4,这是可以实现的。我的新任务要求我最多存储10^9。我个人认为STL没有那么大的空间,他们抛出了错误。你知道在这种情况下还有其他有效的散列方法吗?这是一种非常简单的方法,但我正在尝试使用从折叠和stl中学到的知识 对方法的解释: 1.创建一个向量列表(用于输入目的,可以是任意的) 2.保留一个主向量v,用于存储主折叠向量 3.使用的stl包括在折叠前保持检查是否存在顺序 输入集
std::vector<int> x ={1,2,3};
std::vector<int> y ={7,8,9};
std::vector<int> z ={1,2,3};
std::vector<int> a ={1,2,3};
std::vector<int> v5 = {11,1,1,1}; //as mentioned in question
std::vector<int> v6 = {1,1,1,1}; //as mentioned in question
我知道可以有很多改进,在某些情况下可能会失败。这只是尝试之一。请随意批评并帮助我改进如果您定义向量的完整顺序,您可以通过两种方式进行合理有效的查找:
- 将现有向量存储在
或std::set
中。这些是有序的容器类,具有相当有效的成员资格/查找方法std::map
- 将现有向量按排序顺序存储在
中,并使用std::vector
std::binary\u search
对向量排序的默认选择是字典顺序。这是由
操作符提供的。实现这一点的简单方法是将向量存储在另一个向量中,并使用std::sort()函数族,使用std::lexigraphical_compare作为排序谓词,保持向量的顺序。这将允许在O(log(n))摊销时间内对列表进行二进制搜索,代价是半昂贵的排序操作,这可能通过在加载向量列表时对其进行重分类或分区来减少
但是,比这更有效的方法是将向量存储为trie(),其中沿trie的每条路径都存储来自向量的唯一序列。根据数据中的差异,这可能更节省空间,并且加法和搜索都是O(log(n))操作
不过,请恕我直言,10^4元素实际上是一个很小的数字。我的经验是,排序和搜索算法的效率差异只有在数据集在10^6-10^7范围内时才会在现代硬件上显现出来。在这个规模之下,最简单、最友好的缓存算法往往胜出
另一种选择是,如果你只是追求原始速度,而你要扫描的向量列表是众所周知的静态的,那就是使用有限状态机来接受/拒绝你的输入。像Ragel这样的工具可以很快解决这些问题。将向量转换为逗号分隔的字符串应该不会很繁琐。这似乎是解决这个问题的最简单的方法。我认为散列函数会帮助你考虑在TIE结构中存储向量。然后你可以很容易地检查它effeciently@hiteshn97是什么让您认为std::set
不是有效的类型?这里namespace std{templatebool operator注意到您使用了a.cbegin()而不是a.begin(),是否有特定原因?或者只是个人选择?可能是为了确保不更改向量的内容?可能是因为您通过引用传递。是否正确?为什么在这种情况下返回true?if(*a_it<*b_it)return true;
考虑字母顺序:确定是否“cat”
,您首先检查'c'
。如果是这样,您就知道“cat”
排在第一位--您不需要检查任何其他字符,您知道结果是true
。此外,我还使用了cbegin()
强调输入是恒定的。我对向量的折叠不太了解。我尝试用谷歌搜索,但没有找到任何有用的资源。你能给我一个链接吗?你的算法的时间复杂度是多少。O(n)太大了!第一个方法。我没有得到它。我能理解的是你;重新排序向量,但是你的算法能区分{1,2,3}和{3,2,1}吗?
#include <iostream>
#include <vector>
#include <algorithm>
#include <list>
template <typename T>
void Concat(std::vector<T>& v, const std::vector<T>& v2)
{
v.insert(v.end(), v2.begin(), v2.end());
}
template <typename T>
void Concat(std::vector<T>& v, const T& value)
{
v.push_back(value);
}
template<typename T, typename... Args>
void push_back_vec(std::vector<T>& v, Args&&... args)
{
(Concat(v, args), ...);
}
int main()
{
std::vector<int> v;
std::list<std::vector<int> > m ;
std::vector<int> x ={1,2,3};
std::vector<int> y ={7,8,9};
std::vector<int> z ={1,2,3};
std::vector<int> a ={1,2,3};
std::vector<int> v5 = {11,1,1,1};
std::vector<int> v6 = {1,1,1,1};
m.push_back(x);
m.push_back(y);
m.push_back(z);
m.push_back(a);
m.push_back(v5);
m.push_back(v6);
for (std::list<std::vector<int> >::iterator it1 = m.begin(); it1 != m.end(); ++it1)
{
if (std::includes(v.begin(), v.end(), (*it1).begin(), (*it1).end()))
{
std::cout<<"Already present"<<std::endl;
}
else
{
push_back_vec(v,(*it1));
}
}
for (int i : v) std::cout << i << ' ';
}
Already present
Already present
1 2 3 7 8 9 11 1 1 1 1 1 1 1 Program ended with exit code: 0
bool operator<(const std::vector<int> &a, const std::vector<int> &b) {
auto a_it = a.cbegin();
auto b_it = b.cbegin();
while(a_it < a.cend() && b_it < b.cend()) {
if(*a_it < *b_it) {
return true;
}
if(*b_it < *a_it) {
return false;
}
++a_it;
++b_it;
}
if(a_it == a.cend() && b_it < b.cend()) {
return true;
}
return false;
}