问题:我希望数组A[6] = {6, 5, 4, 3, 2, 1}
为A[6] = {5, 3, 1, 1, 1, 1}
。换句话说 - "删除"每隔一个值从0开始,并将所有其他值移到左侧。
我的尝试:
为此,我将使用此代码,其中a - 数组A的相关部分的长度(具有未删除元素的部分),ind - 我想要删除的值的索引。
for (int j = ind; j < n; j++)
A[j] = A[j+1];
但是,我无法使用这样的代码来实现这一点:
void deleting(int A[], int& a, int ind){
for (int j = ind; j < a; j++)
A[j] = A[j+1];
a--;
}
int A[6] = {6, 5, 4, 3, 2, 1};
a = 6
for (int i = 0; i < a; i+=2)
deleting(A, a, i);
运行此代码后,我得到了A[6] = {5, 4, 2, 1, 1507485184, 1507485184}
。因此,它删除了索引0,3处的元素。为什么删除第3个索引?
答案 0 :(得分:8)
有两种方法可以做到这一点:
遍历数组,将每个偶数n-i
的最后i
个元素前移一个位置,或者
弄清楚最终的状态,然后直截了当地说。最终状态是第一个n/2
个地方array[i]=array[2*i + 1]
,最后n/2
个地方只是最后一个元素的副本。
第一种方法是您要求的方法,但它会执行多次冗余复制操作,第二种方法可以避免。
关于您的实现问题,请检查j=n-1
时发生的情况,并记住A[n]
不是数组的有效元素。
我建议无论如何都要使copy-everything-forward操作成为自己的函数(或者你可以使用memcpy)
答案 1 :(得分:4)
对于这些类型的问题(就地数组操作),将一个索引或指针保存到数组中是个好主意,因为&#34;读取&#34;另一个你在写作的地方。&#34;例如:
void odds(int* a, size_t len) {
int* writep = a;
int* readp = a + 1;
while (readp < a + len) { // copy odd elements forward
*writep++ = *readp;
readp += 2;
}
while (writep < a + len - 1) { // replace rest with last
*writep++ = a[len - 1];
}
}
答案 2 :(得分:2)
只是为了踢,这是一个不使用循环的版本:
#include <algorithm>
#include <cstddef>
#include <iostream>
#include <iterator>
#include <utility>
#include <initializer_list>
template <typename T, std::size_t Size>
std::ostream& print(std::ostream& out, T const (&array)[Size]) {
out << "[";
std::copy(std::begin(array), std::end(array) -1,
std::ostream_iterator<T>(out, ", "));
return out << std::end(array)[-1] << "]";
}
template <std::size_t TI, std::size_t FI, typename T, std::size_t Size>
bool assign(T (&array)[Size]) {
array[TI] = array[FI];
return true;
}
template <typename T, std::size_t Size,
std::size_t... T0>
void remove_even_aux(T (&array)[Size],
std::index_sequence<T0...>) {
bool aux0[] = { assign<T0, 2 * T0 + 1>(array)... };
bool aux1[] = { assign<Size / 2 + T0, Size - 1>(array)... };
}
template <typename T, std::size_t Size>
void remove_even(T (&array)[Size]) {
remove_even_aux(array, std::make_index_sequence<Size / 2>());
}
int main() {
int array[] = { 6, 5, 4, 3, 2, 1 };
print(std::cout, array) << "\n";
remove_even(array);
print(std::cout, array) << "\n";
}
答案 3 :(得分:1)
如果C ++算法是一个选项,我倾向于默认选择它们:
auto *const end_A = A + (sizeof(A)/sizeof(*A));
auto *new_end = std::remove_if(
A, end_A,
[&A](int const& i) { return (&i - A) % 2 == 0; });
// Now "erase" the remaining elements.
std::fill(new_end, end_A, 0);
std::remove_if
算法只移动与谓词不匹配的元素(在我们的例子中,测试地址是MOD(2)= 0),并std::move
将它们移到最后。这是到位的。新的&#34;结束&#34;是return,然后我将其索引并将元素设置为0。
答案 4 :(得分:0)
因此,如果它必须是一个数组,解决方案将是这样的:
{{1}}
你首先遍历数组的前半部分,每隔一个数字“移动”到前面,然后你循环通过其余数字填充最后一个数字。
答案 5 :(得分:0)
对于其他答案的更多功能版本:
#include <iostream>
template<typename InputIt, typename T>
void filter(InputIt begin, InputIt end, T const& defaultvalue)
{
InputIt fastforward = begin;
InputIt slowforward = begin;
fastforward++; // starts at [1], not [0]
while (fastforward < end)
{
*slowforward = *fastforward;
++slowforward;
++ ++fastforward;
}
while (slowforward < end) // fill with default value
{
*slowforward++ = defaultvalue;
}
}
int main()
{
int A[6] = {6, 5, 4, 3, 2, 1};
std::cout << "before: ";
for (auto n : A)
std::cout << n << ", ";
std::cout << std::endl;
filter(A, A+6, 1);
std::cout << "after: ";
for (auto n : A)
std::cout << n << ", ";
std::cout << std::endl;
}
输出:
before: 6, 5, 4, 3, 2, 1,
after: 5, 3, 1, 1, 1, 1,
这适用于std::array<bool>
,std::vector<std::string>
,std::unordered_set<void*>::iterator
等。
答案 6 :(得分:0)
执行此操作的常用方法是保留两个索引:一个用于您正在修改的条目,另一个用于您打算处理的条目
const auto size = sizeof(A) / sizeof(int);
// N.b. if size == 1 entire array is garbage
int i = 0;
for (int nv = 1; nv < size; ++i, nv += 2)
A[i] = A[nv];
--i;
// Significative array is now [0;N/2[, fill with last now
for (int j = i + 1; j < size; ++j)
A[j] = A[i];
这授予了就地修改方式。
答案 7 :(得分:0)
您可以合并std::remove_if
和std::fill
来执行此操作
示例代码:
#include <algorithm>
#include <iostream>
#include <iterator>
int main()
{
int A[6] = {6, 5, 4, 3, 2, 1};
auto endX = std::remove_if(std::begin(A),std::end(A),[&A](const int& i){return (&i-A)%2==0;});
if(endX!=std::begin(A))//in case nothing remained, although not possible in this case
std::fill(endX,std::end(A),*(endX-1));
//else /*something to do if nothing remained*/
for(auto a : A)std::cout<<a<<' ';
}