C++从数组中删除一个最大值和零

C++从数组中删除一个最大值和零,c++,arrays,C++,Arrays,我有一个里面有10个值的双数组,首先我的函数应该从数组中查找并删除最大值,如果这个值在数组中只有一次,然后从数组中删除零值。在这一点上,我们不能使用任何向量来解决这个问题 void calculations(double first[], int& n) { int k = 0; double max1= first[0]; for (int i = 0; i < n; i++) { if (first[i] > max1)

我有一个里面有10个值的双数组,首先我的函数应该从数组中查找并删除最大值,如果这个值在数组中只有一次,然后从数组中删除零值。在这一点上,我们不能使用任何向量来解决这个问题

void calculations(double first[], int& n)
{
    int k = 0;
    double max1= first[0];

    for (int i = 0; i < n; i++)
    {
        if (first[i] > max1)
        {
            max1 = first[i];
        }
            if (first[i] == max1)
            {
            k++;
            }
            if (k < 2)
            {
                for (int i = max1; i < n - 1; i++)
                {
                first[i] = first[i + 1];
                n--;
                }
            }
    }

    for (int i = 0; i < n; i++)
    {
        if (first[i] == 0)
        {
            first[i] = first[i + 1];
            n--;
        }
    }

    for (int i = 0; i < n; i++)
    {
        cout << first[i] << endl;
    }
}
为了从数组中删除一个元素,您需要将所有剩余的元素向上移动一个,这样array[i]=array[i+1]

另一种方法是指示阵列插槽可供重用


请参阅std::vector::erase和std::array

读起来很像编程课程作业?不管怎样,我会采用两次通过的方法:

第一关有两个任务:

找到最大的元素并记住它;还要确保它只在那里一次。 数一数零的数目。 代码:

if (n == 0)
    return; //just to be safe

size_t max_value = first[0];
bool max_value_is_unique = true;
size_t zeroes = first[0] == 0 ? 1 : 0;
//start at 1, since we already looked at first[0] above!
for (size_t i = 1; i < n; ++i) {
    //oh, it's a 0; count it!
    if (first[i] == 0)
        zeroes++;

    //check if this is equal to or bigger than current maximum
    if (first[i] == max_value)
        max_value_is_unique = false;
    else if (first[i] > max_value) {
        max_value = first[i];
        max_value_is_unique = true;
    }
}
否则,运行第二遍:

这只会将条目从右侧移动到当前位置。 一旦达到0或最大值,移动距离就会增加,因为我们想跳过该值

//move all entries some distance "to the left"
int distance = 0;
for (size_t i = 0; i < n - distance; /* no increment! */) {
    bool might_inc = true;
    //we skip the current value in case it's a zero or the maximum value
    if ((max_value_is_unique && first[i] == max_value) || first[i] == 0)
        distance++;

    if (distance > 0) {
        if (i + distance < n) {
            //we might reach out of the array here, so this line guarded
            first[i] = first[i + distance];
            //since we just copied some value to the current `i`, we need to take a look at that `i` it again - it might be 0 or the maximum value
            might_inc = false;
        } else
            //if we would reach out of the array, write 0
            first[i] = 0;
     }

     if (might_inc)
         i++;
}

//you didn't specify it, so I'll just set the remaining entries to 0
for (int i = n - distance; i < n; ++i) {
    first[i] = 0;
}
我没有像全零一样检查角落案例,但我认为它应该有效。 如果您知道有X个尾随零,则速度可能会更快,而不是复制&然后检查复制的值,您可以在复制之前检查值。但是,正如我所说的,这看起来像是一个练习,长度是10,那么好,应该可以了-


如果您不知道大小,那么这是一种奇特的数据类型,它总是足够大,足以处理您的整个内存。在这段代码中,您很可能只编写无符号int或int。但是我认为大小应该是更好的样式,在适当的地方严格使用大小是一种很好的做法。

您的代码完全错误

您的第一个for循环应该只用于查找最大值和计数,每次找到较大的值时,您都需要重置计数器k

然后使用另一个for循环删除值,i+1可能超出边界,n-将阻止您遍历整个数组

用于删除值的for循环也是错误的,应该有两个数字来指示保留和探测的索引


例如,要从[1,0,0,4]中删除0,您的代码将以[1,0,4,4]结尾,并将大小更改为2

您的删除在搜索范围内-这是错误的

你实际上不需要计算最大值

不能通过simple==比较浮点值,如float、double和long double。你需要测量它们之间的差异,如果它小于某个小的公差值,认为它们相等。

所以。。。试试这个:

#include <iostream>
#include <cstddef>
#include <cmath>
#include <cstdlib>

void remove_all(double* array, std::size_t& size, double val) {
    double eps = 1e-9; 
    std::size_t k = 0, tail = 0;
    while (k + tail < size) {
        if (std::fabs(array[k + tail] - val) < eps) // correct floating point numbers equality compare
            ++tail;
        else {
            array[k] = array[k + tail];
            ++k;
        }
    }
    size -= tail;
}

void remove_max_and_zeros(double* array, std::size_t& size) {
    //-- find max element in array --
    double maxVal = array[0];
    for (std::size_t k = 0; k < size; ++k) 
        if (maxVal < array[k])
            maxVal = array[k];
    //-- remove max element from array --
    remove_all(array, size, maxVal);
    //-- remove zeros from array --
    remove_all(array, size, 0.0);
}

int main()
{
    const std::size_t maxSize = 10;
    double arr[maxSize] = { 1.1, 1.3, 0.0, 2.5, 0.0, -5.8, 2.5, 0.0, 0.0001, 0.0 };
    std::size_t size = maxSize;

    for (std::size_t k = 0; k < size; ++k)
        std::cout << arr[k] << " ";
    std::cout << std::endl;

    remove_max_and_zeros(arr, size);

    for (std::size_t k = 0; k < size; ++k)
        std::cout << arr[k] << " ";
    std::cout << std::endl;
    return 0;
}

不能从c样式数组中删除元素。从数组中删除元素是什么意思?…更重要的是:你的问题是什么?请阅读,然后编辑你的帖子,使其成为一个问题。删除后,最大值和零值数组应smaller@SemyonBurov你不能,我的意思是你不能。即使您移动了值,元素仍然存在,而向量在删除元素后可能很容易收缩其容量出于某种原因,此代码没有打印任何结果这只是一个快速写下,我没有费心测试它。。。所以可能有错误,但它应该传达我希望的总体想法。如果你仔细看,你会发现我遗漏了一个打印循环。。。你觉得你应该能做到吗;
#include <iostream>
#include <cstddef>
#include <cmath>
#include <cstdlib>

void remove_all(double* array, std::size_t& size, double val) {
    double eps = 1e-9; 
    std::size_t k = 0, tail = 0;
    while (k + tail < size) {
        if (std::fabs(array[k + tail] - val) < eps) // correct floating point numbers equality compare
            ++tail;
        else {
            array[k] = array[k + tail];
            ++k;
        }
    }
    size -= tail;
}

void remove_max_and_zeros(double* array, std::size_t& size) {
    //-- find max element in array --
    double maxVal = array[0];
    for (std::size_t k = 0; k < size; ++k) 
        if (maxVal < array[k])
            maxVal = array[k];
    //-- remove max element from array --
    remove_all(array, size, maxVal);
    //-- remove zeros from array --
    remove_all(array, size, 0.0);
}

int main()
{
    const std::size_t maxSize = 10;
    double arr[maxSize] = { 1.1, 1.3, 0.0, 2.5, 0.0, -5.8, 2.5, 0.0, 0.0001, 0.0 };
    std::size_t size = maxSize;

    for (std::size_t k = 0; k < size; ++k)
        std::cout << arr[k] << " ";
    std::cout << std::endl;

    remove_max_and_zeros(arr, size);

    for (std::size_t k = 0; k < size; ++k)
        std::cout << arr[k] << " ";
    std::cout << std::endl;
    return 0;
}