分段 排序函数实现中的错误
Segmentation Fault in the implementation of a sorting function
我正在尝试实现一种基于为我的编程课提供的伪代码的排序算法,我和我的搭档一直收到(核心转储(错误,通常是分段错误。我知道这通常意味着程序正在尝试访问不允许的内存,但我不确定如何解决这个问题。
#include <iostream>
#include <cmath>
using namespace std;
void FlipFlopSort(int *Array, int begin, int end){
int length = (end-begin);
float midh = 2*(float)length/3;
midh = ceil(midh);
float midl = (float)length/3;
midl = ceil(midl);
//cout << "size of sorted area = " << length << endl;
if(length<=2){
//cout << "Length = 2" << endl;
if(Array[begin] > Array[begin+1]){
swap(Array[begin], Array[begin+1]);
}
}else{
//cout << "Recursion Begin 1" << endl;
FlipFlopSort(Array, begin, midh);
//cout << "Recursion End" << endl;
FlipFlopSort(Array, midl, end);
//cout << "Recursion Begin 2" << endl;
FlipFlopSort(Array, begin, midh);
}
}
int main(){
// Declare Variables and Read Inputs
int n;
cin >> n;
int Array[n];
for(int i = 0; i < n; i++){
cin >> Array[i];
}
FlipFlopSort(Array, 0, n);
for(int i = 0; i<n; i++){
if(i != (n-1)){
cout << Array[i] << " ";
}else{
cout << Array[i] << endl;
}
}
return 0;
}
让我们从:
int n;
cin >> n;
int Array[n];
- 为什么 n 是有符号类型?数组大小不能声明为有符号类型。
- C++严格禁止在堆栈上声明可变大小的数组(即你所做的方式(。它也是 C 的一个已弃用的功能。你应该写:
int* Array = new int[n];
您可能遇到分段错误的原因之一是由于以下行:
if (length <= 2) {
//cout << "Length = 2" << endl;
if (Array[begin] > Array[begin + 1]) {
swap(Array[begin], Array[begin + 1]);
}
}
- 如果长度小于或等于 2,是否意味着它至少有 2 个元素?它可能有 0 或 1。您应该在函数的开头添加一个检查:
void FlipFlopSort(int *Array, int begin, int end){
int length = (end-begin);
if (length <= 1) {
return;
}
...
}
另一个原因是,因为您计算的是中间大小而不是索引,这意味着您不会向它们添加开头。
考虑:开始=100,结束=103。 -> 长度 = 3,midl = 1,midh = 2。意义?不!在这种情况下,这些不是有效的索引。你应该写的
midh += begin;
midl += begin;
经过他们的计算。
最后,你应该避免使用浮点数(除非你真的需要(,所以我会写:
const int midl = begin + length / 3;
const int midh = begin + 2 * midl;
它不等同于你写的,但它仍然有效,而你的是有风险的(上限值是可疑的,因为你可能会发现自己在数组的末尾(。
void FlipFlopSort(int* Array, int begin, int end) {
const int length = end - begin;
if (length <= 1) {
return;
}
const int midh = begin + 2 * length / 3;
const int midl = begin + length / 3;
//cout << "size of sorted area = " << length << endl;
if (length <= 2) {
//cout << "Length = 2" << endl;
if (Array[begin] > Array[begin + 1]) {
swap(Array[begin], Array[begin + 1]);
}
}
else {
FlipFlopSort(Array, begin, midh);
FlipFlopSort(Array, midl, end);
FlipFlopSort(Array, begin, midh);
}
}
您必须确保length
在swap
时至少为 2,否则您将交换出界的数字。您的midl
值和midh
值当前是错误的。它们是相对于begin
,因此您需要向它们添加begin
。但是,您可以将midl
添加到Array
本身,并跳过函数中的begin
参数以简化界面。
我还会将浮点std::ceil
运算替换为整数版本。
// A function to do integer division and return the ceil value
size_t DivCeil(size_t dividend, size_t divisor) {
return 1U + ((dividend - 1U) / divisor);
}
void FlipFlopSort(int* Array, size_t length) {
if(length > 2) {
// calculate midl & midh
size_t midl = DivCeil(length, 3U);
size_t midh = DivCeil(2U * length, 3U);
FlipFlopSort(Array, midh);
// add midl to Array and sub midl from length
FlipFlopSort(Array + midl, length - midl);
FlipFlopSort(Array, midh);
} else if(length == 2) {
if(Array[1] < Array[0]) {
// swap the values
std::swap(Array[0], Array[1]);
}
} // else length < 2 ... don't do anything
}
#include <iostream>
#include <vector>
int main() {
size_t n;
if(std::cin >> n) { // check that the user entered a number
// don't use VLA:s, use a std::vector instead
std::vector<int> Array(n);
for(size_t i = 0; i < Array.size(); ++i) {
std::cin >> Array[i];
}
FlipFlopSort(Array.data(), Array.size());
for(int value : Array) {
std::cout << value << 'n';
}
}
}
如果您希望排序算法更加通用并可用于标准容器,则可以将输入参数替换为迭代器。
例:
#include <algorithm> // std::iter_swap
#include <iterator> // std::distance, std::next
// A function to do integer division and return the ceil value
template<typename T>
T DivCeil(T dividend, T divisor) {
return 1 + ((dividend - 1) / divisor);
}
template<typename It>
void FlipFlopSort(It begin, It end) {
auto length = std::distance(begin, end); // iterator version of "length = end-begin"
static constexpr decltype(length) two = 2; // constant of the same type as length
static constexpr decltype(length) three = 3; // -"-
if(length > two) {
// calculate midl & midh iterators
auto midl = std::next(begin, DivCeil(length, three));
auto midh = std::next(begin, DivCeil(two * length, three));
FlipFlopSort(begin, midh);
FlipFlopSort(midl, end);
FlipFlopSort(begin, midh);
} else if(length == two) {
if(*std::next(begin) < *begin) {
// swap the values pointed at by the iterators
std::iter_swap(begin, std::next(begin));
}
} // else length == 1 or 0 ... don't do anything
}
用法:
#include <iostream>
#include <vector>
int main() {
size_t n;
if(std::cin >> n) {
std::vector<int> Array(n);
for(size_t i = 0; i < Array.size(); ++i) {
std::cin >> Array[i];
}
FlipFlopSort(std::begin(Array), std::end(Array));
for(int value : Array) {
std::cout << value << 'n';
}
}
}
相关文章:
- 在c++中实现LinkedList时,应出现未处理的错误
- 尝试使用继承和模板实现CRTP.Visual Studio正在生成编译器错误
- 在 c++ 中实现 Trie 时出现分段错误
- C++ 实现模板单例类时出现链接错误
- 内存错误低于在C++年实现埃拉托色尼筛分时的预期
- C++数组队列实现方法错误
- 实现 DFS 在较短的输入下工作正常,但在较大的输入下会抛出分段错误
- 分段 排序函数实现中的错误
- 尝试从头开始实现Leetcode的FizzBuzz多线程问题。收到"libc++abi.dylib: terminating"错误
- 使用 std::forward_list 返回错误的队列实现
- 在我的trie实现中出现分段错误
- 在 c++ 中实现链表时出现分段错误
- 比较迭代器会使程序崩溃,而不会在自定义气泡排序实现中出现错误
- 如何知道C2259 VS 2017错误未实现哪种方法?
- 筛子的埃拉托色尼错误实现
- BAD_ALLOC错误实现向量调整大小函数时
- 头文件中包含.cpp重新定义错误-实现通用堆栈
- 程序没有给出期望的输出.FIFO的错误实现
- 这是卡达内算法的错误实现吗?
- 双链表错误实现Deque