删除数组中的偶数并移动元素
Deleting an even number in an array and shift the elements
我正在尝试编写一个代码,其中对偶数进行研究,然后删除偶数,然后移动所有其他元素。
i是偏移量,是数组中元素的实际位置。
k是偶数在数组中的位置
int k;
for(i=0; i < N; i++)
{
if(Array[i] % 2 == 0)
{
for(k=i+1; k < N; k++)
{
Array[k-1] = Array[k];
}
N--;
}
}
Array=[2,10,3,5,8,7,3,3,7,10]偶数应该去掉,但是一个10
留在 Array=[10,3,5,7,3,3,7].
现在我花了 3 个多小时来找出我的代码中的错误。
您可以使用 std::vector
和标准函数 std::erase_if
+ 向量 erase
函数来执行此操作:
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> Array = {2, 10, 3, 5, 8, 7, 3, 3, 7, 10};
auto it = std::remove_if(
Array.begin(),
Array.end(),
[](int x) { return (x & 1) == 0 && x != 10; }
);
Array.erase(it, Array.end());
for(int x : Array) {
std::cout << x << "\n";
}
}
输出:
10
3
5
7
3
3
7
10
编辑:困难的做法:
#include <iostream>
int main() {
int Array[] = {2, 10, 3, 5, 8, 7, 3, 3, 7, 10};
size_t N = sizeof(Array) / sizeof(int);
for(size_t i = 0; i < N;) {
if((Array[i] & 1) == 0 && Array[i] != 10) {
for(size_t k = i + 1; k < N; ++k) {
Array[k - 1] = Array[k];
}
--N;
} else
++i; // only step i if you didn't shift the other values down
}
for(size_t i = 0; i < N; ++i) {
std::cout << Array[i] << "\n";
}
}
或更简单:
#include <iostream>
int main() {
int Array[] = {2, 10, 3, 5, 8, 7, 3, 3, 7, 10};
size_t N = sizeof(Array) / sizeof(int);
size_t k = 0;
for(size_t i = 0; i < N; ++i) {
if((Array[i] & 1) || Array[i] == 10) {
// step k after having saved this value
Array[k++] = Array[i];
}
}
N = k;
for(size_t i = 0; i < N; ++i) {
std::cout << Array[i] << "\n";
}
}
C++ 中惯用的解决方案是使用 STL 算法。
这个例子使用了 C 风格的数组。
int Array[100] = {2,10,3,5,8,7,3,3,7,10};
int N = 10;
// our remove_if predicate
auto removeEvenExceptFirst10 = [first10 = true](int const& num) mutable {
if (num == 10 && first10) {
first10 = false;
return false;
}
return num % 2 == 0;
};
auto newN = std::remove_if(
std::begin(Array), std::begin(Array) + N,
removeEvenExceptFirst10
);
N = std::distance(std::begin(Array), newN);
这似乎是某种家庭作业或学校作业。那么发布的代码的实际问题是什么?
就是当你在索引i
处删除一个偶数时,你把原来在索引i + 1
处的数字放到索引i
中。然后继续外循环迭代,这将检查索引 i + 1
,这是数组中原始 i + 2
位置的数字。所以从 Array[i + 1]
开始,现在在 Array[i]
的数字永远不会被检查。
解决此问题的一个简单方法是在递减 N
时递减 i
。
虽然已经回答了,但我看不出人们通过双 for 循环驱动它的原因,一遍又一遍地重复移动数据,每次减少。
我完全同意所有关于使用容器的建议。此外,算法解决方案不需要容器(您 可以 在本机数组上使用它),但容器仍然使它更容易和更清洁。也就是说...
我在上面的一般评论中描述了这个算法。你不需要嵌套循环。您需要一个读指针和一个写指针。 就是这样.
#include <iostream>
size_t remove_even(int *arr, size_t n)
{
int *rptr = arr, *wptr = arr;
while (n-- > 0)
{
if (*rptr % 2 != 0)
*wptr++ = *rptr;
++rptr;
}
return (wptr - arr);
}
int main()
{
int arr[] = { 2,10,3,5,8,7,3,3,7,10 };
size_t n = remove_even(arr, sizeof arr / sizeof *arr);
for (size_t i=0; i<n; ++i)
std::cout << arr[i] << ' ';
std::cout << '\n';
}
输出
3 5 7 3 3 7
如果您认为这没有什么不同,我邀请您用一百万个随机整数填充一个数组,然后尝试两种解决方案(嵌套 for 循环方法与您在上面看到的方法)。
在原生数组上使用 std::remove_if
。
仅为了清楚起见,上面的代码基本上完成了标准算法 std::remove_if
所做的工作。我们需要做的就是提供迭代器(数组偏移量和大小会很好地工作),并知道如何解释结果。
#include <iostream>
#include <algorithm>
int main()
{
int arr[] = { 2,10,3,5,8,7,3,3,7,10 };
auto it = std::remove_if(std::begin(arr), std::end(arr),
[](int x){ return x%2 == 0; });
for (size_t i=0; i<(it - arr); ++i)
std::cout << arr[i] << ' ';
std::cout << '\n';
}
相同的结果。
我正在尝试编写一个代码,其中对偶数进行研究,然后删除偶数,然后移动所有其他元素。
i是偏移量,是数组中元素的实际位置。
k是偶数在数组中的位置
int k;
for(i=0; i < N; i++)
{
if(Array[i] % 2 == 0)
{
for(k=i+1; k < N; k++)
{
Array[k-1] = Array[k];
}
N--;
}
}
Array=[2,10,3,5,8,7,3,3,7,10]偶数应该去掉,但是一个10 留在 Array=[10,3,5,7,3,3,7].
现在我花了 3 个多小时来找出我的代码中的错误。
您可以使用 std::vector
和标准函数 std::erase_if
+ 向量 erase
函数来执行此操作:
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> Array = {2, 10, 3, 5, 8, 7, 3, 3, 7, 10};
auto it = std::remove_if(
Array.begin(),
Array.end(),
[](int x) { return (x & 1) == 0 && x != 10; }
);
Array.erase(it, Array.end());
for(int x : Array) {
std::cout << x << "\n";
}
}
输出:
10
3
5
7
3
3
7
10
编辑:困难的做法:
#include <iostream>
int main() {
int Array[] = {2, 10, 3, 5, 8, 7, 3, 3, 7, 10};
size_t N = sizeof(Array) / sizeof(int);
for(size_t i = 0; i < N;) {
if((Array[i] & 1) == 0 && Array[i] != 10) {
for(size_t k = i + 1; k < N; ++k) {
Array[k - 1] = Array[k];
}
--N;
} else
++i; // only step i if you didn't shift the other values down
}
for(size_t i = 0; i < N; ++i) {
std::cout << Array[i] << "\n";
}
}
或更简单:
#include <iostream>
int main() {
int Array[] = {2, 10, 3, 5, 8, 7, 3, 3, 7, 10};
size_t N = sizeof(Array) / sizeof(int);
size_t k = 0;
for(size_t i = 0; i < N; ++i) {
if((Array[i] & 1) || Array[i] == 10) {
// step k after having saved this value
Array[k++] = Array[i];
}
}
N = k;
for(size_t i = 0; i < N; ++i) {
std::cout << Array[i] << "\n";
}
}
C++ 中惯用的解决方案是使用 STL 算法。
这个例子使用了 C 风格的数组。
int Array[100] = {2,10,3,5,8,7,3,3,7,10};
int N = 10;
// our remove_if predicate
auto removeEvenExceptFirst10 = [first10 = true](int const& num) mutable {
if (num == 10 && first10) {
first10 = false;
return false;
}
return num % 2 == 0;
};
auto newN = std::remove_if(
std::begin(Array), std::begin(Array) + N,
removeEvenExceptFirst10
);
N = std::distance(std::begin(Array), newN);
这似乎是某种家庭作业或学校作业。那么发布的代码的实际问题是什么?
就是当你在索引i
处删除一个偶数时,你把原来在索引i + 1
处的数字放到索引i
中。然后继续外循环迭代,这将检查索引 i + 1
,这是数组中原始 i + 2
位置的数字。所以从 Array[i + 1]
开始,现在在 Array[i]
的数字永远不会被检查。
解决此问题的一个简单方法是在递减 N
时递减 i
。
虽然已经回答了,但我看不出人们通过双 for 循环驱动它的原因,一遍又一遍地重复移动数据,每次减少。
我完全同意所有关于使用容器的建议。此外,算法解决方案不需要容器(您 可以 在本机数组上使用它),但容器仍然使它更容易和更清洁。也就是说...
我在上面的一般评论中描述了这个算法。你不需要嵌套循环。您需要一个读指针和一个写指针。 就是这样.
#include <iostream>
size_t remove_even(int *arr, size_t n)
{
int *rptr = arr, *wptr = arr;
while (n-- > 0)
{
if (*rptr % 2 != 0)
*wptr++ = *rptr;
++rptr;
}
return (wptr - arr);
}
int main()
{
int arr[] = { 2,10,3,5,8,7,3,3,7,10 };
size_t n = remove_even(arr, sizeof arr / sizeof *arr);
for (size_t i=0; i<n; ++i)
std::cout << arr[i] << ' ';
std::cout << '\n';
}
输出
3 5 7 3 3 7
如果您认为这没有什么不同,我邀请您用一百万个随机整数填充一个数组,然后尝试两种解决方案(嵌套 for 循环方法与您在上面看到的方法)。
在原生数组上使用 std::remove_if
。
仅为了清楚起见,上面的代码基本上完成了标准算法 std::remove_if
所做的工作。我们需要做的就是提供迭代器(数组偏移量和大小会很好地工作),并知道如何解释结果。
#include <iostream>
#include <algorithm>
int main()
{
int arr[] = { 2,10,3,5,8,7,3,3,7,10 };
auto it = std::remove_if(std::begin(arr), std::end(arr),
[](int x){ return x%2 == 0; });
for (size_t i=0; i<(it - arr); ++i)
std::cout << arr[i] << ' ';
std::cout << '\n';
}
相同的结果。