C ++中具有负索引的类似数组的数据结构
Posted
技术标签:
【中文标题】C ++中具有负索引的类似数组的数据结构【英文标题】:Array like data structure with negetive index in C++ 【发布时间】:2018-09-22 10:28:30 【问题描述】:我需要一个结构来跟踪某些项目的存在。我只是想获取一个数组 a0....aN 并将元素标记为 a[0]=0,a[1]=0,a[2]=1........(a[i]=1
如果元素存在,a[i]=0
如果元素不存在)。
但项目范围从 -1000 到 +1000。可以通过将负值范围从 1001 到 2000 来完成。我需要知道 c++ 中是否有任何其他数据结构可以像数组一样工作并且具有负索引。感谢您的宝贵时间。
【问题讨论】:
不,没有。但不是映射 only 负值,我会移动 all 它们,所以你不需要区分,只需添加偏移量(即 -1000 是映射到 0,1000 映射到 2000)。当然,你可以把它包装到你自己的容器类中…… 相关:***.com/q/4306/1025391 考虑使用其他类型的数据结构,而不是使用数组,并强制以某种方式对数组元素的索引和项目标识符使用相同的值。std::map<int, bool>
或 std::set<int>
似乎是适合这项工作的工具
@GianPaolo 我们也应该考虑unordered
的对应物。另一方面,仅移动索引就可以保证O(1)
运行时与有序容器的 O(log(n)) 相比,并且不需要像无序容器那样进行散列和冲突处理。
@Aconcagua 您可以随时将std::set<int>
替换为您自己基于位数组编写的数据结构,只要您发现这是一项性能关键优化。如果不是这样,那么这样做可能会导致不必要的意外错误并浪费时间。
【参考方案1】:
map
仅用于此目的,具有任何基本/用户定义数据类型的 key/index
。见-http://www.cplusplus.com/reference/map/map/
您的案例示例:
#include <iostream>
#include <map>
#include <string>
int main ()
std::map<int, int> mymap;
mymap[-1]=1;
mymap[-2]=0;
mymap[-3]=1;
std::cout << mymap[-1] << '\n';
std::cout << mymap[-2] << '\n';
std::cout << mymap[-3] << '\n';
return 0;
字符示例:
#include <iostream>
#include <map>
#include <string>
int main ()
std::map<char,std::string> mymap;
mymap['a']="an element";
mymap['b']="another element";
mymap['c']=mymap['b'];
std::cout << "mymap['a'] is " << mymap['a'] << '\n';
std::cout << "mymap['b'] is " << mymap['b'] << '\n';
std::cout << "mymap['c'] is " << mymap['c'] << '\n';
std::cout << "mymap['d'] is " << mymap['d'] << '\n';
std::cout << "mymap now contains " << mymap.size() << " elements.\n";
return 0;
【讨论】:
欢迎 :) 我的荣幸【参考方案2】:您可以创建自己的支持 -ve 索引的数据结构。只需在索引中添加一个偏移量,同时将它们存储在一个数组中。
class MyArray
int *arr;
public:
MyArray(int offset)
arr = new int[2*offset]; // size must to double the offset
~MyArray()
delete arr;
void add(int index, int val)
arr[index + offset] = val;
void get(int index)
return arr[index + offset];
然后你可以使用你的类来添加和获取任何索引的元素。
MyArray arr = MyArray(1000); // pass max -ve index as offset
arr.add(10, -150);
cout << arr.get(100);
【讨论】:
据我理解的问题,范围应包括-offset和+offset,所以我们需要2*offset + 1的大小... 我宁愿提供标准索引运算符(const 和非 const 之一),而不是自定义 add/get,返回引用。 为什么使用new[]
会引入更多内存泄漏等问题?只需使用std::vector<int>
。您的 MyArray
类泄漏内存并且不能安全地复制或分配。
在这种情况下std::array
可能更合适
在这种情况下,我建议使用std::bitset
而不是任何类型的整数数组。【参考方案3】:
我需要一个结构来跟踪某些项目的存在。
如果您想要的是集合语义,请使用集合数据结构。
无需实现自定义数组包装器。
您可以为此使用std::set
(或std::unordered_set
)。请记住"premature optimization is the root of all evil"。
插入存在的值,忽略缺失的值。无需担心负指数。
您可以使用std::set::find()
或std::set::count()
方法来检查项目的存在。查看文档以找到一些示例代码。
如果您以后发现这是一项性能关键优化,您可以随时将std::set<int>
替换为您自己基于位数组编写的数据结构。如果不是这样,过早地这样做可能会导致意外错误的不必要来源和浪费时间。
供参考:
http://en.cppreference.com/w/cpp/container/set http://en.cppreference.com/w/cpp/container/unordered_set http://en.cppreference.com/w/cpp/container/set/find http://en.cppreference.com/w/cpp/container/set/count How to check that an element is in a std::set?【讨论】:
实际上,我们有两种选择:将当前元素或缺失的元素存储在集合中,两者都同样复杂,那么您会选择哪一个(尤其是在过早优化方面......)? 如果我们提前知道一种或另一种情况总是例外,选择使集合更小的变体不应该再是 PO。你同意吗? @Aconcagua 我猜默认应该是跟踪当前项目。从一个空集开始,然后在给定数据的情况下填充它似乎比从一个包含所有可能项目的集合开始,然后删除实际存在的项目更容易。但正如您所说,相对性能可能会因实际数据(和查询模式)而异。【参考方案4】:最有效的方法是移动数组索引,使它们都为非负数。在您的情况下,只需使用 a[i+1000]
就足够了。
如果您确实需要使用负索引,它也是可能的。 C / C ++使用表的地址计算数组元素的内存地址,然后将索引值添加到它。使用负数只是指向放置在您的表格之前的内存区域(这不是您通常想要的)。
int a[2001];
int *b = &a[1000];
int x = b[-1000]; // This points to 1000 places before b which translates to a[0] (valid place)
另一种方法是使用容器。然后可以将任何数字转换为字符串并存储在适当的容器中。
【讨论】:
【参考方案5】:我认为@Rajev 的回答几乎没问题。我刚刚用std::vector
替换了一个普通数组。因此,内存管理是安全的,复制和移动很容易。
template <typname T>
class MyArray
private:
std::vector<T> arr;
public:
MyArray(int offset)
arr.resize(2*offset); // size must to double the offset
void set(int index, int val)
arr[index + offset] = val;
void get(int index)
return arr[index + offset];
您可以通过重载 MyArray 的 operator []
来进一步扩展它。
【讨论】:
以上是关于C ++中具有负索引的类似数组的数据结构的主要内容,如果未能解决你的问题,请参考以下文章