- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个需要内置排序的应用程序,我希望用 STXXL 提供的排序替换现有的排序机制。我已经使用 STXXL 成功地测试了它,但我的问题是,虽然特定的排序运行需要对固定长度的字符串进行操作,但长度是在运行时确定的,可以在 10 字节到 4000 字节之间的任何地方。如果实际长度很小,总是允许 4000 字节显然是非常低效的。
对于那些不熟悉 STXXL 的人,我认为这个问题大致等同于在编译时不知道对象大小的情况下定义一个 std::vector。但是,我不是 C++ 专家 - 该应用程序是用 C 语言编写的。
在我的测试中,这是我正在排序的类型:
struct string80
{
char x[80];
};
这是 STXXL 分类器的类型定义:
typedef stxxl::sorter<string80, sort_comparator80> stxxl_sorter80;
问题是我不想将数组大小硬编码为“80”。
我能想到的唯一解决方案是定义许多不同长度的结构并在运行时选择最接近的。我错过了一个把戏吗?我是在用 C 而不是 C++ 来思考吗?
最佳答案
如果我们将大小为 n 的对象(记录)存储在一个平坦的 stxxl::vector of chars 中会怎么样。然后,定义一个基于 stxxl::vector::iterator 的自定义迭代器,它在每次递增时仅跳过 n 个字节。当使用 std::vector 而不是 STXXL 时,这将适用于 std::sort 甚至 tbb::sort。我看到 STXXL 的 ExtIterator 有很多额外的特性。是否可以为这样的迭代器正确定义它们?
#include <vector>
#include <cassert>
#include <cstdlib>
#include <stxxl.h>
#include <iostream>
#include <algorithm>
typedef std::vector<char>::iterator It;
class ObjectValue;
//This class defines a reference object that handles assignment operations
//during a sorting
class ObjectReference
{
public:
ObjectReference() : recordSize_(0) {}
ObjectReference(It ptr, size_t recordSize) : ptr_(ptr), recordSize_(recordSize) {}
void operator = (ObjectReference source) const
{
std::copy(source.ptr_, source.ptr_ + recordSize_, ptr_);
}
void operator = (const ObjectValue & source) const;
It GetIterator() const
{
return ptr_;
}
size_t GetRecordSize() const
{
return recordSize_;
}
private:
It ptr_;
size_t recordSize_;
};
//This class defines a value object that is used when a temporary value of a
//record is required somewhere
class ObjectValue
{
public:
ObjectValue() {}
ObjectValue(ObjectReference prx) : object_(prx.GetIterator(), prx.GetIterator() + prx.GetRecordSize()) {}
ObjectValue(It ptr, size_t recordSize) : object_(ptr, ptr + recordSize) {}
std::vector<char>::const_iterator GetIterator() const
{
return object_.begin();
}
private:
std::vector<char> object_;
};
//We need to support copying from a reference to an object
void ObjectReference::operator = (const ObjectValue & source) const
{
std::copy(source.GetIterator(), source.GetIterator() + recordSize_, ptr_);
}
//The comparator passed to a sorting algorithm. It recieves iterators, converts
//them to char pointers, that are passed to the actual comparator tha handles
//object comparison
template<class Cmp>
class Comparator
{
public:
Comparator() {}
Comparator(Cmp cmp) : cmp_(cmp) {}
bool operator () (const ObjectReference & a, const ObjectReference & b) const
{
return cmp_(&*a.GetIterator(), &*b.GetIterator());
}
bool operator () (const ObjectValue & a, const ObjectReference & b) const
{
return cmp_(&*a.GetIterator(), &*b.GetIterator());
}
bool operator () (const ObjectReference & a, const ObjectValue & b) const
{
return cmp_(&*a.GetIterator(), &*b.GetIterator());
}
bool operator () (const ObjectValue & a, const ObjectValue & b) const
{
return cmp_(&*a.GetIterator(), &*b.GetIterator());
}
private:
Cmp cmp_;
};
//The iterator that operates on flat byte area. If the record size is $n$, it
//just skips $n$ bytes on each increment operation to jump to the next record
class RecordIterator : public std::iterator<std::random_access_iterator_tag, ObjectValue, size_t, RecordIterator, ObjectReference>
{
public:
RecordIterator() : recordSize_(0) {}
RecordIterator(It ptr, size_t recordSize) : ptr_(ptr), recordSize_(recordSize) {}
ObjectReference operator * () const
{
return ObjectReference(ptr_, recordSize_);
}
ObjectReference operator [] (size_t diff) const
{
return *(*this + diff);
}
It GetIterator() const
{
return ptr_;
}
size_t GetRecordSize() const
{
return recordSize_;
}
RecordIterator& operator ++()
{
ptr_ += recordSize_;
return *this;
}
RecordIterator& operator --()
{
ptr_ -= recordSize_;
return *this;
}
RecordIterator operator ++(int)
{
RecordIterator ret = *this;
ptr_ += recordSize_;
return ret;
}
RecordIterator operator --(int)
{
RecordIterator ret = *this;
ptr_ -= recordSize_;
return ret;
}
friend bool operator < (RecordIterator it1, RecordIterator it2);
friend bool operator > (RecordIterator it1, RecordIterator it2);
friend bool operator == (RecordIterator it1, RecordIterator it2);
friend bool operator != (RecordIterator it1, RecordIterator it2);
friend size_t operator - (RecordIterator it1, RecordIterator it2);
friend RecordIterator operator - (RecordIterator it1, size_t shift);
friend RecordIterator operator + (RecordIterator it1, size_t shift);
private:
It ptr_;
size_t recordSize_;
};
bool operator < (RecordIterator it1, RecordIterator it2)
{
return it1.ptr_ < it2.ptr_;
}
bool operator > (RecordIterator it1, RecordIterator it2)
{
return it1.ptr_ > it2.ptr_;
}
bool operator == (RecordIterator it1, RecordIterator it2)
{
return it1.ptr_ == it2.ptr_;
}
bool operator != (RecordIterator it1, RecordIterator it2)
{
return !(it1 == it2);
}
RecordIterator operator - (RecordIterator it1, size_t shift)
{
return RecordIterator(it1.ptr_ - shift * it1.recordSize_, it1.recordSize_);
}
RecordIterator operator + (RecordIterator it1, size_t shift)
{
return RecordIterator(it1.ptr_ + shift * it1.recordSize_, it1.recordSize_);
}
size_t operator - (RecordIterator it1, RecordIterator it2)
{
return (it1.ptr_ - it2.ptr_) / it1.recordSize_;
}
namespace std
{
//We need to specialize the swap for the sorting to work correctly
template<>
void swap(ObjectReference & it1, ObjectReference & it2)
{
ObjectValue buf(it1.GetIterator(), it1.GetRecordSize());
std::copy(it2.GetIterator(), it2.GetIterator() + it2.GetRecordSize(), it1.GetIterator());
std::copy(buf.GetIterator(), buf.GetIterator() + it1.GetRecordSize(), it2.GetIterator());
}
}
//Finally, here is the "user"-defined code. In the example, "records" are
//4-byte integers, although actual size of a record can be changed at runtime
class RecordComparer
{
public:
bool operator ()(const char * aRawPtr, const char * bRawPtr) const
{
const int * aPtr = reinterpret_cast<const int*>(aRawPtr);
const int * bPtr = reinterpret_cast<const int*>(bRawPtr);
return *aPtr < *bPtr;
}
};
int main(int, char*[])
{
size_t size = 100500;
//Although it is a constant, it is easy to change to in runtime
size_t recordSize = sizeof(int);
std::vector<int> intVector(size);
std::generate(intVector.begin(), intVector.end(), rand);
const char * source = reinterpret_cast<const char*>(&intVector[0]);
std::vector<char> recordVector;
std::copy(source, source + recordVector.size(), &recordVector[0]);
RecordIterator begin(recordVector.begin(), recordSize);
RecordIterator end(recordVector.end(), recordSize);
//Sort "records" as blocks of bytes
std::sort(begin, end, Comparator<RecordComparer>());
//Sort "records" as usual
std::sort(intVector.begin(), intVector.end());
//Checking that arrays are the same:
for (; begin != end; ++begin)
{
size_t i = begin - RecordIterator(recordVector.begin(), recordSize);
It it = (*(begin)).GetIterator();
int* value = reinterpret_cast<int*>(&(*it));
assert(*value == intVector[i]);
}
return 0;
}
关于c++ - 是否可以在运行时定义要在 STXXL 中排序的类型的长度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21136337/
SQLite、Content provider 和 Shared Preference 之间的所有已知区别。 但我想知道什么时候需要根据情况使用 SQLite 或 Content Provider 或
警告:我正在使用一个我无法完全控制的后端,所以我正在努力解决 Backbone 中的一些注意事项,这些注意事项可能在其他地方更好地解决......不幸的是,我别无选择,只能在这里处理它们! 所以,我的
我一整天都在挣扎。我的预输入搜索表达式与远程 json 数据完美配合。但是当我尝试使用相同的 json 数据作为预取数据时,建议为空。点击第一个标志后,我收到预定义消息“无法找到任何内容...”,结果
我正在制作一个模拟 NHL 选秀彩票的程序,其中屏幕右侧应该有一个 JTextField,并且在左侧绘制弹跳的选秀球。我创建了一个名为 Ball 的类,它实现了 Runnable,并在我的主 Draf
这个问题已经有答案了: How can I calculate a time span in Java and format the output? (18 个回答) 已关闭 9 年前。 这是我的代码
我有一个 ASP.NET Web API 应用程序在我的本地 IIS 实例上运行。 Web 应用程序配置有 CORS。我调用的 Web API 方法类似于: [POST("/API/{foo}/{ba
我将用户输入的时间和日期作为: DatePicker dp = (DatePicker) findViewById(R.id.datePicker); TimePicker tp = (TimePic
放宽“邻居”的标准是否足够,或者是否有其他标准行动可以采取? 最佳答案 如果所有相邻解决方案都是 Tabu,则听起来您的 Tabu 列表的大小太长或您的释放策略太严格。一个好的 Tabu 列表长度是
我正在阅读来自 cppreference 的代码示例: #include #include #include #include template void print_queue(T& q)
我快疯了,我试图理解工具提示的行为,但没有成功。 1. 第一个问题是当我尝试通过插件(按钮 1)在点击事件中使用它时 -> 如果您转到 Fiddle,您会在“内容”内看到该函数' 每次点击都会调用该属
我在功能组件中有以下代码: const [ folder, setFolder ] = useState([]); const folderData = useContext(FolderContex
我在使用预签名网址和 AFNetworking 3.0 从 S3 获取图像时遇到问题。我可以使用 NSMutableURLRequest 和 NSURLSession 获取图像,但是当我使用 AFHT
我正在使用 Oracle ojdbc 12 和 Java 8 处理 Oracle UCP 管理器的问题。当 UCP 池启动失败时,我希望关闭它创建的连接。 当池初始化期间遇到 ORA-02391:超过
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 9 年前。 Improve
引用这个plunker: https://plnkr.co/edit/GWsbdDWVvBYNMqyxzlLY?p=preview 我在 styles.css 文件和 src/app.ts 文件中指定
为什么我的条形这么细?我尝试将宽度设置为 1,它们变得非常厚。我不知道还能尝试什么。默认厚度为 0.8,这是应该的样子吗? import matplotlib.pyplot as plt import
当我编写时,查询按预期执行: SELECT id, day2.count - day1.count AS diff FROM day1 NATURAL JOIN day2; 但我真正想要的是右连接。当
我有以下时间数据: 0 08/01/16 13:07:46,335437 1 18/02/16 08:40:40,565575 2 14/01/16 22:2
一些背景知识 -我的 NodeJS 服务器在端口 3001 上运行,我的 React 应用程序在端口 3000 上运行。我在 React 应用程序 package.json 中设置了一个代理来代理对端
我面临着一个愚蠢的问题。我试图在我的 Angular 应用程序中延迟加载我的图像,我已经尝试过这个2: 但是他们都设置了 src attr 而不是 data-src,我在这里遗漏了什么吗?保留 d
我是一名优秀的程序员,十分优秀!