c ++取消数组元素,并相应地取消第二个数组中的元素 [英] c++ cancel array elements and cancel elements in second array accordingly
问题描述
int
数组被排序。第一个数组用重复值填充,第二个数组用第一个数组中指示无效值的值填充,最后一个数组存储 float
值。例如: int n = 11;
int * val = new int [n] {1,1,2,2,2,2,3,4,5,5,5};
float * val2 = new float [n] {0.5,0.5,0.25,0.25,0.25,0.25,1,1,0.33,0.33,0.33};
int * invalid = new int [2] {2,5};
现在复制存储在 val
到有效
(即除 2
和 5
)并将对应于 val
中的有效值的 val2
中的值复制到 valid2
,即除
0.25
和 0.33
之外的每个值,因为 code>对应于
0.25
(所有2个都位于 2-5
作为0.25的位置)和 5
对应于 0.33
(所有5个都位于 8-10
作为0.33的)。
然后输出应该像这样
int * valid = new int [4] {1,1,3 ,4};
float * valid2 = new int [4] {0.5,0.5,1,1}
如何使用for循环有效地实现这个?我想指出,我不能切换到容器像矢量或列表,因为我知道将有这方面的意见。我需要使用数组。
我们的初学者应该互相帮助:)
由于数组无效
只有两个元素,因此您可以使用以下直接方法
#include< iostream>
#include< algorithm>
#include< iterator>
int main()
{
const size_t N = 11;
int * val = new int [N] {1,1,2,2,2,2,3,4,5,5,5};
float * val2 = new float [N] {0.5,0.5,0.25,0.25,0.25,0.25,1,1,0.33,0.33,0.33};
int * invalid = new int [2] {2,5};
int * valid = nullptr;
float * valid2 = nullptr;
auto is_valid_element = [=](int x){return x!= invalid [0]&& x!= invalid [1]; };
auto n = std :: count_if(val,val + N,is_valid_element);
if(n)
{
valid = new int [n];
valid2 = new float [n];
for(size_t i = 0,j = 0; i {
if(is_valid_element(val [i]))
{
valid [j] = val [i];
valid2 [j] = val2 [i];
j ++;
}
}
}
if(n)
{
std :: copy(valid,valid + n,std :: ostream_iterator< int>(std :: cout,));
std :: cout<< std :: endl;
std :: copy(valid2,valid2 + n,std :: ostream_iterator< float>(std :: cout,));
std :: cout<< std :: endl;
}
delete [] val;
delete [] val2;
delete [] invalid;
delete [] valid;
delete [] valid2;
return 0;
}
程序输出是
1 1 3 4
0.5 0.5 1 1
如果数组无效或数组val很大,那么首先可以在数组val中找到数组的第一个元素的下界无效,并从下界元素的索引开始。
因此,在循环之前,您应该使用标准算法 std :: lower_bound
std :: upper_bound
找到循环的数组val中的第一个和最后一个实际索引。要确定数组中是否存在元素 invalid
,可以使用标准算法 std :: binary_search
。
这里是一个演示程序
#include< iostream>
#include< algorithm>
#include< iterator>
int main()
{
const size_t N = 11;
const size_t M = 2;
int * val = new int [N] {1,1,2,2,2,2,3,4,5,5,5};
float * val2 = new float [N] {0.5,0.5,0.25,0.25,0.25,0.25,1,1,0.33,0.33,0.33};
int * invalid = new int [M] {2,5};
int * valid = nullptr;
float * valid2 = nullptr;
auto it = std :: lower_bound(val,val + N,invalid [0]);
size_t lower = std :: distance(val,it);
it = std :: upper_bound(it,val + N,invalid [M-1]);
size_t upper = std :: distance(val,it);
auto invalid_element = [=](int x){return std :: binary_search(invalid,invalid + M,x); };
size_t n = N - std :: count_if(val + lower,val + upper,invalid_element);
if(n)
{
valid = new int [n];
valid2 = new float [n];
size_t i = 0;
for(size_t j = 0; j< lower; i ++,j ++)
{
valid [i] = val [j]
valid2 [i] = val2 [j];
}
for(size_t j = lower; j< upper; j ++)
{
if(!invalid_element(val [j]))
{
valid [i] = val [j];
valid2 [i] = val2 [j];
i ++;
}
}
for(size_t j = upper; j {
valid [i] j]。
valid2 [i] = val2 [j];
}
}
if(n)
{
std :: copy(valid,valid + n,std :: ostream_iterator< int> std :: cout,));
std :: cout<< std :: endl;
std :: copy(valid2,valid2 + n,std :: ostream_iterator< float>(std :: cout,));
std :: cout<< std :: endl;
}
delete [] val;
delete [] val2;
delete [] invalid;
delete [] valid;
delete [] valid2;
return 0;
}
其输出为
1 1 3 4
0.5 0.5 1 1
p>这个程序比第一个程序更大,但同时更高效:)
你可以做更专业的程序。例如你可以替换语句
size_t n = N-std :: count_if(val + lower,val + upper,invalid_element) ;
size_t n = N-std :: count_if(std :: next(val,lower),std :: next(val,upper),invalid_element);
或者使用带索引的循环,而不是使用循环迭代器。
然而,最有效的方法是编写一个类似于标准算法 std :: set_difference
p>
这是一个演示程序
#include< iostream>
#include< algorithm>
#include< iterator>
int main()
{
const size_t N = 11;
const size_t M = 2;
int * val = new int [N] {1,1,2,2,2,2,3,4,5,5,5};
float * val2 = new float [N] {0.5,0.5,0.25,0.25,0.25,0.25,1,1,0.33,0.33,0.33};
int * invalid = new int [M] {2,5};
int * valid = nullptr;
float * valid2 = nullptr;
auto it = std :: lower_bound(val,val + N,invalid [0]);
size_t lower = std :: distance(val,it);
it = std :: upper_bound(it,val + N,invalid [M-1]);
size_t upper = std :: distance(val,it);
size_t i; // index in val;
size_t j; // index in invalid;
size_t n; // val中有效元素的总数
i = lower;
j = 0;
n = 0;
//计数无效元素
while(i!= upper)
{
if(val [i] {
++ i;
}
else if(invalid [j]< val [i])
{
++ j;
}
else
{
++ i;
++ n;
}
}
n = N - n;
if(n)
{
valid = new int [n];
valid2 = new float [n];
size_t k; // index in valid and valid2
i = j = k = 0;
while(i!= N&& j!= M)
{
if(val [i] {
valid [k] = val [i];
valid2 [k] = val2 [i];
++ k;
++ i;
}
else if(invalid [j]< val [i])
{
++ j;
}
else
{
++ i;
}
}
for(; i!= N; k ++,i ++)
{
valid [k] = val [i]
valid2 [k] = val2 [i];
}
}
if(n)
{
std :: copy(valid,valid + n,std :: ostream_iterator< int> std :: cout,));
std :: cout<< std :: endl;
std :: copy(valid2,valid2 + n,std :: ostream_iterator< float>(std :: cout,));
std :: cout<< std :: endl;
}
delete [] val;
delete [] val2;
delete [] invalid;
delete [] valid;
delete [] valid2;
return 0;
}
其输出与上述相同
1 1 3 4
0.5 0.5 1 1
In c++ I got three arrays, the int
arrays are sorted. The first array is filled with repeating values, the second one is filled with values that indicate an invalid value in the first array and the last one stores float
values. For example:
int n = 11;
int * val = new int[n]{1, 1, 2, 2, 2, 2, 3, 4, 5, 5, 5};
float * val2 = new float[n] {0.5, 0.5, 0.25, 0.25, 0.25, 0.25, 1, 1, 0.33, 0.33, 0.33};
int * invalid = new int[2]{ 2, 5};
Now copy the valid values stored in val
to valid
(i.e. every value except for 2
and 5
) and copy the values in val2
corresponding to the valid values in val
to valid2
, i.e. every value except 0.25
and 0.33
, because 2
corresponds to 0.25
(all 2's are on positions 2-5
as the 0.25's), and 5
corresponds to 0.33
(all 5's are on positions 8-10
as the 0.33's).
Then the output shall be like this
int * valid = new int[4]{ 1, 1, 3, 4};
float * valid2 = new int[4]{0.5, 0.5, 1, 1}
How can I implement this efficiently using a for loop? I want to point out that I can not switch to containers like vector or list, because I know there will be comments going in that direction. I explicitly need to work with arrays.
We beginners should help each other.:)
As the array invalid
has only two elements then you can use the following straightforward approach
#include <iostream>
#include <algorithm>
#include <iterator>
int main()
{
const size_t N = 11;
int *val = new int[N] { 1, 1, 2, 2, 2, 2, 3, 4, 5, 5, 5 };
float *val2 = new float[N] { 0.5, 0.5, 0.25, 0.25, 0.25, 0.25, 1, 1, 0.33, 0.33, 0.33 };
int *invalid = new int[2] { 2, 5 };
int *valid = nullptr;
float *valid2 = nullptr;
auto is_valid_element = [=]( int x ) { return x != invalid[0] && x != invalid[1]; };
auto n = std::count_if( val, val + N, is_valid_element );
if ( n )
{
valid = new int[n];
valid2 = new float[n];
for ( size_t i = 0, j = 0; i < N; i++ )
{
if ( is_valid_element( val[i] ) )
{
valid[j] = val[i];
valid2[j] = val2[i];
j++;
}
}
}
if ( n )
{
std::copy( valid, valid + n, std::ostream_iterator<int>( std::cout, " " ) );
std::cout << std::endl;
std::copy( valid2, valid2 + n, std::ostream_iterator<float>( std::cout, " " ) );
std::cout << std::endl;
}
delete [] val;
delete [] val2;
delete [] invalid;
delete [] valid;
delete [] valid2;
return 0;
}
The program output is
1 1 3 4
0.5 0.5 1 1
If the array invalid or array val is large then you can at first find the lower bound of the first element of the array invalid in the array val and start with the index of the lower bound element. The same is valid for upper bound.
So before the loop you should use standard algorithms std::lower_bound
and std::upper_bound
to find the first and the last actual indices in the array val for the loop. To determine whether an element is present in the array invalid
you can use standard algorithm std::binary_search
.
Here is a demonstrative program
#include <iostream>
#include <algorithm>
#include <iterator>
int main()
{
const size_t N = 11;
const size_t M = 2;
int *val = new int[N] { 1, 1, 2, 2, 2, 2, 3, 4, 5, 5, 5 };
float *val2 = new float[N] { 0.5, 0.5, 0.25, 0.25, 0.25, 0.25, 1, 1, 0.33, 0.33, 0.33 };
int *invalid = new int[M] { 2, 5 };
int *valid = nullptr;
float *valid2 = nullptr;
auto it = std::lower_bound( val, val + N, invalid[0] );
size_t lower = std::distance( val, it );
it = std::upper_bound( it, val + N, invalid[M-1] );
size_t upper = std::distance( val, it );
auto invalid_element = [=]( int x ) { return std::binary_search( invalid, invalid + M, x ); };
size_t n = N - std::count_if( val + lower, val + upper, invalid_element );
if ( n )
{
valid = new int[n];
valid2 = new float[n];
size_t i = 0;
for ( size_t j = 0; j < lower; i++, j++ )
{
valid[i] = val[j];
valid2[i] = val2[j];
}
for ( size_t j = lower; j < upper; j++ )
{
if ( !invalid_element( val[j] ) )
{
valid[i] = val[j];
valid2[i] = val2[j];
i++;
}
}
for ( size_t j = upper; j < N; i++, j++ )
{
valid[i] = val[j];
valid2[i] = val2[j];
}
}
if ( n )
{
std::copy( valid, valid + n, std::ostream_iterator<int>( std::cout, " " ) );
std::cout << std::endl;
std::copy( valid2, valid2 + n, std::ostream_iterator<float>( std::cout, " " ) );
std::cout << std::endl;
}
delete [] val;
delete [] val2;
delete [] invalid;
delete [] valid;
delete [] valid2;
return 0;
}
Its output is
1 1 3 4
0.5 0.5 1 1
This program is more large than the first one but at the same time it is more efficient.:)
You can do the program more professionally looked. For example you can substitute statement
size_t n = N - std::count_if( val + lower, val + upper, invalid_element );
for
size_t n = N - std::count_if( std::next( val, lower ), std::next( val, upper ), invalid_element );
Or instead of using loops with indices you could use loops with iterators.
However the most efficient approach is to write an algorithm similar to the standard algorithm std::set_difference
.
Here is a demonstrative program
#include <iostream>
#include <algorithm>
#include <iterator>
int main()
{
const size_t N = 11;
const size_t M = 2;
int *val = new int[N] { 1, 1, 2, 2, 2, 2, 3, 4, 5, 5, 5 };
float *val2 = new float[N] { 0.5, 0.5, 0.25, 0.25, 0.25, 0.25, 1, 1, 0.33, 0.33, 0.33 };
int *invalid = new int[M] { 2, 5 };
int *valid = nullptr;
float *valid2 = nullptr;
auto it = std::lower_bound( val, val + N, invalid[0] );
size_t lower = std::distance( val, it );
it = std::upper_bound( it, val + N, invalid[M-1] );
size_t upper = std::distance( val, it );
size_t i; // index in val;
size_t j; // index in invalid;
size_t n; // total number of valid elements in val
i = lower;
j = 0;
n = 0;
// counting invalid elements
while ( i != upper )
{
if ( val[i] < invalid[j] )
{
++i;
}
else if ( invalid[j] < val[i] )
{
++j;
}
else
{
++i;
++n;
}
}
n = N - n;
if ( n )
{
valid = new int[n];
valid2 = new float[n];
size_t k; // index in valid and valid2
i = j = k = 0;
while ( i != N && j != M )
{
if ( val[i] < invalid[j] )
{
valid[k] = val[i];
valid2[k] = val2[i];
++k;
++i;
}
else if ( invalid[j] < val[i] )
{
++j;
}
else
{
++i;
}
}
for ( ; i != N; k++, i++ )
{
valid[k] = val[i];
valid2[k] = val2[i];
}
}
if ( n )
{
std::copy( valid, valid + n, std::ostream_iterator<int>( std::cout, " " ) );
std::cout << std::endl;
std::copy( valid2, valid2 + n, std::ostream_iterator<float>( std::cout, " " ) );
std::cout << std::endl;
}
delete [] val;
delete [] val2;
delete [] invalid;
delete [] valid;
delete [] valid2;
return 0;
}
Its output is the same as shown above
1 1 3 4
0.5 0.5 1 1
这篇关于c ++取消数组元素,并相应地取消第二个数组中的元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!