根据 std::sort() 实现 qsort()
Implement qsort() in terms of std::sort()
出于愚蠢的原因,我想编写一个具有以下签名的函数(其中(^)
表示Apple对C++的"blocks"扩展(:
extern "C" my_qsort_b(void *arr, size_t nelem, size_t eltsize, int (^)(const void *, const void *));
其中函数以std::sort
实现。(请注意,我不能使用 qsort
,因为它需要函数指针,而不是块指针;我不能使用 qsort_b
,因为我可能没有 Apple 的标准库。我不会接受涉及qsort_b
的答案。
是否可以使用 std::sort
在C++中实现此功能? 还是我必须从头开始编写自己的快速排序实现?
请提供工作代码。魔鬼在这里的细节中;我不是在问"我如何使用std::sort
?
看起来更难——尽管std::sort
显然比qsort
更强大,但两者之间的阻抗不匹配足以使在前者方面实现后者成为一项艰巨的任务。
不过,这是可以做到的。这是使用 std::sort
作为主力的 my_qsort_b
(这里称为 block_qsort
(的工作实现。该代码改编自qsort
的实现,std::sort
作为练习完成,并进行了简单的修改以通过调用块进行比较。该代码经过测试,可以在x86_64 Linux上编译和使用clang++ 3.3。
#include <algorithm>
#include <cstring>
struct Elem {
char* location;
size_t size;
bool needs_deleting;
Elem(char* location_, size_t size_):
location(location_), size(size_), needs_deleting(false) {}
Elem(const Elem& rhs): size(rhs.size) {
location = new char[size];
*this = rhs;
needs_deleting = true;
}
Elem& operator=(const Elem& rhs) {
memcpy(location, rhs.location, size);
return *this;
}
~Elem() {
if (needs_deleting)
delete[] location;
}
};
struct Iter: public std::iterator<std::random_access_iterator_tag, Elem> {
Elem elem;
Iter(char* location, size_t size): elem(location, size) {}
// Must define custom copy/assignment to avoid copying of iterators
// making copies of elem.
Iter(const Iter& rhs): elem(rhs.elem.location, rhs.elem.size) {}
Iter& operator=(const Iter& rhs) {elem.location = rhs.elem.location; return *this;}
char* adjust(ptrdiff_t offset) const {
return elem.location + ptrdiff_t(elem.size) * offset;
}
// Operations required for random iterator.
Iter operator+(ptrdiff_t diff) const {return Iter(adjust(diff), elem.size);}
Iter operator-(ptrdiff_t diff) const {return Iter(adjust(-diff), elem.size);}
ptrdiff_t operator-(const Iter& rhs) const {
return (elem.location - rhs.elem.location) / ptrdiff_t(elem.size);
}
Iter& operator++() {elem.location=adjust(1); return *this;}
Iter& operator--() {elem.location=adjust(-1); return *this;}
Iter operator++(int) {Iter old = *this; ++*this; return old;}
Iter operator--(int) {Iter old = *this; --*this; return old;}
bool operator!=(const Iter& rhs) const {return elem.location != rhs.elem.location;}
bool operator==(const Iter& rhs) const {return elem.location == rhs.elem.location;}
bool operator<(const Iter& rhs) const {return elem.location < rhs.elem.location;}
Elem& operator*() {return elem;}
};
struct Cmp_adaptor {
typedef int (^Qsort_comparator)(const void*, const void*);
Qsort_comparator cmp;
Cmp_adaptor(Qsort_comparator cmp_) : cmp(cmp_) {}
bool operator()(const Elem& a, const Elem& b) {
return cmp(a.location, b.location) < 0;
}
};
void block_qsort(void* base, size_t nmemb, size_t size,
int (^compar)(const void *, const void *))
{
Iter begin = Iter(static_cast<char*>(base), size);
std::sort(begin, begin + nmemb, Cmp_adaptor(compar));
}
如果需要从 C 调用block_qsort
,你可以将其声明extern "C"
,因为它在其接口中不使用C++功能。若要测试函数,请编译并运行以下附加代码:
// test block_qsort
#include <iostream>
#include <cstring>
int main(int argc, char** argv)
{
// sort argv[1..argc].
block_qsort(argv + 1, argc - 1, sizeof (char*),
^int (const void* a, const void* b) {
return strcmp(*(char**) a, *(char**) b);
});
for (++argv; *argv; argv++)
std::cout << *argv << std::endl;
return 0;
}
要使用std::sort
,你必须编写一个迭代器类和一个将块包装在函子对象中的类。自己实现快速排序似乎是一个较短的选择。
顺便说一句:块应该返回布尔值,而不是无效,对吧?
从这个开始:
struct memblockref {
void* location;
size_t size;
memblockref( void* loc, size_t s ):location(loc), size(s) {}
memblockref& operator=( memblockref const& right ) {
Assert( size == right.size );
memcpy( location, right.location, std::min( size, right.size ));
return *this;
}
private:
memblockref( memblockref const& ) = delete; // or leave unimplemented in C++03
memblockref() = delete; // or leave unimplemented in C++03
};
然后使用 http://www.boost.org/doc/libs/1_52_0/libs/iterator/doc/iterator_facade.html 创建内存缓冲区的 memblockref 迭代器。
然后将块转换为函数指针,或将其包装在 lambda 或函子中,并调用 std::sort
,您可以在其中根据左右memblockref
的location
字段调用块。
您可能还必须专攻swap
或iter_swap
,但可能不是。
- 如果没有malloc,链表实现将失败
- 如何在c++中实现处理器调度模拟器
- 如何在c++中使用引用实现类似python的行为
- 实现无开销push_back的最佳方法是什么
- 使用简单类型列表实现的指数编译时间.为什么
- 如何在BST的这个简单递归实现中消除警告
- 实现一个在集合上迭代的模板函数
- 我应该实现右值推送功能吗?我应该使用std::move吗
- 如何正确实现和访问运算符的各种自定义枚举器
- C++Union/Struct位域的实现和可移植性
- 这个极客对极客的trie实现是否存在内存泄漏问题
- 在c++中实现LinkedList时,应出现未处理的错误
- 为左值和右值的包装器实现C++范围
- 使用模板进行堆栈实现; "name followed by :: must be a class or namespace"
- 使用GSoap实现ONVIF
- 在用于格式4的arm模拟器中实现功能时的一个问题
- 用于AVX的ln(x)的实现,m256
- 用常见虚拟函数实现的任意组合来实现派生类的正确方法是什么
- 有没有办法避免具有实现QSort的全局变量
- 根据 std::sort() 实现 qsort()