gpt4 book ai didi

c++ - 在 C++ 中使用归并排序计算倒置

转载 作者:塔克拉玛干 更新时间:2023-11-03 06:11:01 25 4
gpt4 key购买 nike

我正在研究我的前几个算法以培养我的 C++ 技能,目前正在编写一种使用合并排序计算倒置的方法。我已经设法将一个有效的合并排序放在一起,但我在跟踪倒置次数时遇到了一些麻烦。关于从这里去哪里的任何想法?我怎样才能跟踪这样的递归算法的反转次数?此外,我在互联网旅行中看到了几个不同的实现,并且发现大多数人偏离了 std::vector 方法,知道为什么吗?感谢您的帮助,我的代码在下面!

#include <iostream>
#include <math.h>
#include <vector>

using namespace std;

vector<int> print(vector<int> input){

for(int i=0; i<input.size(); i++){
cout<<input[i]<<",";
}
cout<<endl;
return input;
}


vector<int> merge(vector<int> left,vector<int> right){

//set up some varibles
vector<int> output;
int i=0;
int j=0;

//loop through the lists and merge
while(i<left.size() && j<right.size()){

//push the smallest of the two to the vector output
if(left[i]<=right[j]){
output.push_back(left[i]);
i+=1;
}
if(left[i]>right[i]){
output.push_back(right[j]);
j+=1;
}
}

//push the remnants of the vectors to output
for(i; i<left.size(); i++){
output.push_back(left[i]);
}

for(j; j<right.size(); j++){
output.push_back(right[j]);
}

return output;
}//end merge

vector<int> merge_sort(vector<int> input){
//check the size of the vector
if(input.size()<2){
return input;
}

else{

//int new vectors
vector<int> left;
vector<int> right;
vector<int> output;

//find the middle of the input vector
int middle=(input.size())/2;

//build the left vector
for(int i=0; i<middle; i++){
left.push_back(input[i]);
}

//build the right vector
for(int i=middle; i<input.size(); i++){
right.push_back(input[i]);
}

//make recursive calls
left=merge_sort(left);
right=merge_sort(right);

//call merge
output=merge(left,right);


return output;
}
}


int main()
{
vector<int> output;
vector<int> input;

input.push_back(2);
input.push_back(1);
input.push_back(10);
input.push_back(4);

output=merge_sort(input);

print(output);


}

最佳答案

好消息:从这里计算倒置非常容易。

想想你的“合并”方法。每次将左侧 vector 中的元素放入输出时,都不会改变其相对于右侧元素的位置。另一方面,每次从右 vector 中添加一个元素时,您都将其放在左 vector 中仍待处理的所有元素“之前”,而当它之前位于它们“之后”时,即创建 (left.size - i) “反转”。

如果需要,您可以通过归纳法轻松证明这一点。

所以答案很简单:将一个 int* 传递给您的合并方法,并在您每次从右 vector 中压入一个元素时将其递增 (left.size - i)。


编辑:工作代码示例

#include <iostream>
#include <vector>
// removed useless dependency math.h

using namespace std;

// void type -> does not return anything
void print (vector<int> input) {
// range-based for loop (since C++ 11)
// no brackets -> only one instruction in for loop
for(int i : input)
cout << i << ",";
}

vector<int> merge (vector<int> left, vector<int> right, int * inv_count) {
vector<int> output;
// multiple variable definition of the same type
int i=0, j=0;

// spaces around "<", after "while", before "{" for readability
while (i < left.size() && j < right.size()) {

// one-instruction trick again
if (left[i] <= right[j])
// i++ is evaluated to <previous value of i> and then increments i
// this is strictly equivalent to your code, but shorter
// check the difference with ++i
output.push_back(left[i++]);
// else because the two conditions were complementary
else {
output.push_back(right[j++]);
// pointer incrementation
*inv_count += (left.size() - i);
}
}

// first field of for ommited because there is no need to initialize i
for(; i < left.size(); i++)
output.push_back(left[i]);

for(; j < right.size(); j++)
output.push_back(right[j]);

return output;
}

vector<int> merge_sort (vector<int> input, int * inv_count) {
// no-braces-idiom again
// spaces around "<" and after "if" for readability
if (input.size() < 2)
return input;

// no need for else keyword because of the return

// multiple variable definition
vector<int> left, right;

int middle = input.size() / 2;

// one-instruction for loop
for(int i=0; i < middle; i++)
left.push_back(input[i]);

for(int i=middle; i < input.size(); i++)
right.push_back(input[i]);

// no need for intermediate variable
return merge( merge_sort(left, inv_count),
merge_sort(right, inv_count),
inv_count);
}

// consistent convention : brace on the same line as function name with a space
int main () {
// vector initialization (valid only since C++ 11)
vector<int> input = {2, 1, 10, 4, 42, 3, 21, 7};

int inv_count = 0;

// No need for intermediate variables again, you can chain functions
print( merge_sort(input, &inv_count) );

// The value inv_count was modified although not returned
cout << "-> " << inv_count << " inversions" << endl;
}

我修改了您的代码以包含一些常用的 C++ 习语。因为您使用了 C++14 标记,所以我还使用了仅自 C++11 起可用的技巧。我不建议在任何地方都使用所有这些技巧,将它们包含在这里是因为这是一种很好的学习体验。

我建议您在深入研究 C++ 之前阅读有关指针的内容。

另请注意,此代码绝不是最优的:创建了太多中间 vector ,并且 vector 在这里没有用,数组就足够了。但我会把这个留到下一次。

关于c++ - 在 C++ 中使用归并排序计算倒置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49091710/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com