有没有一种简单的方法来排序char *的数组? C ++

时间:2008-11-24 15:33:56

标签: c++ sorting in-place external-sorting

我在文件中有一个char*数组。 我工作的公司将数据存储在平面文件中。有时数据会被排序,但有时却不是。 我想对文件中的数据进行排序。

现在我可以从头开始编写代码来执行此操作。 有没有更简单的方法?

当然,就地排序是最好的选择。我正在处理大文件并且内存很少。但我会考虑所有选择。

所有字符串都是相同的长度。

这是一些示例数据:

the data is of fixed length
the Data is of fixed length
thIS data is of fixed lengt

这将代表三条长度为28的记录。该应用程序知道长度。每条记录以CRLF(\r\n)结尾,但这种情况无关紧要。

9 个答案:

答案 0 :(得分:15)

template<size_t length> int less(const char* left, const char* right) {
    return memcmp(left, right, length) < 0;
}

std::sort(array, array + array_length, less<buffer_length>);

答案 1 :(得分:6)

如果无法将数据放入RAM中,请使用GNU排序程序(外部):它将对任意大小的文件进行排序,文件越大,创建过程的额外成本就越小。

答案 2 :(得分:5)

您可以在数组本机数据类型的STL中使用算法,而不仅仅是在STL容器上。使用std :: sort的另一个建议不会像发布的那样工作,因为当字符串不相同时strcmp返回一个值为所有比较的值为true,而不仅仅是左边小于右边的值手边 - 这是std :: sort想要的;左侧返回true的二元谓词小于右侧。

这有效:

struct string_lt : public std::binary_function<bool, char, char>
{
    bool operator()(const char* lhs, const char* rhs)
    {
        int ret = strcmp(lhs, rhs);
        return ret < 0;
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
    char* strings [] = {"Hello", "World", "Alpha", "Beta", "Omega"};
    size_t numStrings = sizeof(strings)/sizeof(strings[0]);

    std::sort(&strings[0], &strings[numStrings], string_lt());

    return 0;
}

答案 3 :(得分:3)

boost::bind可以做到:

// ascending
std::sort(c, c + size,  boost::bind(std::strcmp, _1, _2) < 0); 

// descending
std::sort(c, c + size,  boost::bind(std::strcmp, _1, _2) > 0); 

编辑:字符串不以空值终止:

// ascending
std::sort(c, c + array_size,  boost::bind(std::memcmp, _1, _2, size) < 0); 

// descending
std::sort(c, c + array_size,  boost::bind(std::memcmp, _1, _2, size) > 0); 

答案 4 :(得分:2)

可能最简单的方法是使用旧的stdlib.h函数qsort。 这应该有效:

qsort( array, num_elements, sizeof( char* ), strcmp )

请注意,这是标准C,只适用于英文文本。

如果你有一个String对象列表,那么在C ++中可以做其他事情。

如果您使用的是Linux并编写了gtk或Qt应用程序,那么我建议您事先查看这些库。

答案 5 :(得分:2)

如果文件很大且不适合RAM,您可以使用bin/bucket排序将数据拆分为较小的文件,最后将这些文件聚合在结果文件中。其他响应显示如何对每个桶文件进行排序。

答案 6 :(得分:0)

在C语言中对字符串数组进行排序的规范方法,因此在C ++中使用可用但不一定推荐的方法,使用间接级别strcmp()

static int qsort_strcmp(const void *v1, const void *v2)
{
    const char *s1 = *(char * const *)v1;
    const char *s2 = *(char * const *)v2;
    return(strcmp(s1, s2));
}

static void somefunc(void)   // Or omit the parameter altogether in C++
{
    char **array = ...assignment...
    size_t num_in_array = ...number of char pointers in array...
    ...
    qsort(array, num_in_array, sizeof(char *), qsort_strcmp);
    ...more code...
}

答案 7 :(得分:0)

有些事情会浮现在脑海中:

  1. 如果您的数据太大而无法放入内存,您可能只想在内存中建立文件偏移量的索引,然后对文件进行内存映射以访问字符串(取决于您的操作系统)。
  2. 就地将需要批次的内存副本。如果可以,请使用shell排序。然后,一旦您知道了最终的顺序,就可以更容易地在线性时间内对字符串进行重新排序。
  3. 如果字符串的长度都相同,那么确实需要基数排序。如果你不熟悉基数排序,这里的基本思路是:基于比较的排序(std::sortqsort和任何其他通用排序)总是需要O(N log N)时间。基数排序一次比较一个数字(从str[0]开始到str[K-1]为K-lenth字符串),总体上只需要执行O(N)时间。
  4. 咨询互联网,以获得比我能提供的更好的基数排序算法详细描述。除了我所说的,我会避免使用标准的libarary排序工具的所有其他解决方案。不幸的是,它们并没有设计出你的特定问题。

答案 8 :(得分:0)

您可能希望在POSIX投诉操作系统上查看内存映射文件(请参阅http://en.wikipedia.org/wiki/Memory-mapped_file),mmap()函数(http://en.wikipedia.org/wiki/Mmap)。你基本上会得到一个表示文件内容的连续内存的指针。

好的一面是操作系统会根据需要将文件的一部分加载到内存中并再次卸载它们。

一个缺点是,如果有多个进程可能访问该文件,您需要解析某种形式的文件锁定以避免损坏。

另一个缺点是这并不能保证良好的性能 - 要做到这一点,你需要一个排序算法,试图避免不断加载和卸载页面(除非你有足够的内存将整个文件加载到内存中)。

希望这给了你一些想法!