C++:使用 LSD 基数排序崩溃的字符串排序
C++: Sorting strings using LSD radix sort crashing
我编写了一些代码,旨在使用基数排序对字符串数组进行排序,从最低有效位开始。此函数假定所有字符串的长度都相同,并且每个字符都是小写字母。
每当我进入为临时数组赋值的循环时,我都会遇到崩溃。你可以在这里看到我的功能:
#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
我猜我的逻辑有问题,但我这辈子都想不通。
第二次循环后,count[0] 应为零,第三次循环缺少-97。此示例使用大小为 27 而不是 26 的计数解决了该问题。此示例中的第一个循环使用 -96,因此计数 [0] = 0,计数 [1] = # 个 'a' 的实例,计数 [2] = # 个实例的'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;
}
我编写了一些代码,旨在使用基数排序对字符串数组进行排序,从最低有效位开始。此函数假定所有字符串的长度都相同,并且每个字符都是小写字母。
每当我进入为临时数组赋值的循环时,我都会遇到崩溃。你可以在这里看到我的功能:
#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
我猜我的逻辑有问题,但我这辈子都想不通。
第二次循环后,count[0] 应为零,第三次循环缺少-97。此示例使用大小为 27 而不是 26 的计数解决了该问题。此示例中的第一个循环使用 -96,因此计数 [0] = 0,计数 [1] = # 个 'a' 的实例,计数 [2] = # 个实例的'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;
}