C++:使用 LSD 基数排序对字符串进行排序崩溃

Posted

技术标签:

【中文标题】C++:使用 LSD 基数排序对字符串进行排序崩溃【英文标题】:C++: Sorting strings using LSD radix sort crashing 【发布时间】:2015-04-30 21:28:51 【问题描述】:

我编写了一些代码,旨在使用基数排序对字符串数组进行排序,从最低有效数字开始。此函数假定所有字符串的长度相同,并且每个字符都是小写的。

每当我进入将值分配给临时数组的循环时,我都会遇到崩溃。你可以在这里看到我的功能:

#ifndef RADIX_H
#define RADIX_H

#include <string>
#include <iostream>
using namespace std;

void lsd_string_radix(string array[], int array_size, int max_chars)

    string *temp = new string[array_size];

    for(int i = max_chars - 1; i >= 0; i--)
    
        int count[26] = 0;

        for(int j = 0; j < array_size; j++)
        
            count[static_cast<int>(array[j][i]) - 97]++;
        

        for(int j = 1; j <= 26; j++)
        
            count[j] += count[j - 1];
        

        for(int j = 0; j < array_size; j++)
        
            temp[count[static_cast<int>(array[j][i])]++] = array[j]; // crashes here
        

        for(int j = 0; j < array_size; j++)
        
            array[j] = temp[j];
        
    


#endif

我猜我的逻辑有问题,但我一辈子都想不通。

【问题讨论】:

您是否只是在它崩溃的行中缺少-97 string array[] 作为const &amp;std::vector&lt;std::string&gt; 参考值传入的值可能会好很多。积极使用static_cast 进行排序也可能适得其反。为什么不转换和排序?标准容器使这很容易实现。 【参考方案1】:

在第二个循环之后,count[0] 应该为零,而第三个循环缺少 -97。此示例使用大小为 27 而不是 26 的计数解决了问题。此示例中的第一个循环使用 -96,因此 count[0] = 0, count[1] = # instances of 'a's, count[2] = # instances的'b's,...... count[26] = # 'z's 的实例,但它只在第一个循环中使用。这不是必需的,但是将 'z' 的计数放在那里而不是添加 if 语句以避免将计数存储在 count[26] 处更简单。

#include<iomanip>
#include<iostream>
#include <string>

using namespace std;

void lsd_string_radix(string array[], int array_size, int max_chars)

    string *temp = new string[array_size];

    for(int i = max_chars - 1; i >= 0; i--)
    
        int count[27] = 0;

        for(int j = 0; j < array_size; j++)
            count[static_cast<int>(array[j][i]) - 96]++;

        for(int j = 2; j < 26; j++)
            count[j] += count[j - 1];

        for(int j = 0; j < array_size; j++)
            temp[count[static_cast<int>(array[j][i]) - 97]++] = array[j];

        for(int j = 0; j < array_size; j++)
            array[j] = temp[j];
    


int main()

string a[6] = "mnop", "ijkl", "efgh", "uvwx", "qrst", "abcd";
    lsd_string_radix(a, 6, 4);
    for(size_t i = 0; i < 6; i++)
        cout << a[i] << endl;
    return 0;

如果count[]的大小为26,则需要修改第一个循环:

        for(int j = 0; j < array_size; j++)
            if(array[j][i] == 'z')continue;
            count[static_cast<int>(array[j][i]) - 96]++;
        

或者修改前两个循环:

        for(int j = 0; j < array_size; j++)
            count[static_cast<int>(array[j][i]) - 97]++;

        int m = 0;
        int n;    
        for(int j = 0; j < 26; j++)
            n = count[j];
            count[j] = m;
            m += n;
        

【讨论】:

效果很好,非常感谢。你介意解释为什么count[27] 更有意义吗?我仍然不太清楚这个概念。

以上是关于C++:使用 LSD 基数排序对字符串进行排序崩溃的主要内容,如果未能解决你的问题,请参考以下文章

MSD 与 LSD 基数排序

字符串算法—字符串排序(下篇)

在 C++ 崩溃中使用向量向量进行基数排序

数据结构里面的“基数排序”到底是啥

排序6:基数排序

PHP常见排序算法12——基数排序