删除元素后如何返回数组?

Posted

技术标签:

【中文标题】删除元素后如何返回数组?【英文标题】:How can I return the array after deleting an element? 【发布时间】:2021-12-11 05:26:11 【问题描述】:

下面的函数

int* del_element(int* vector, int dim, int el)

    // ...?

正在接收一个动态分配的数组。我可以在里面写什么来删除元素并返回获得的数组?

【问题讨论】:

为什么不使用std::vector 你尝试了吗?为什么要标记vector?使用vector 这将是微不足道的,没有它会不必要地复杂。你能用vector吗? 只是作为一个练习,你应该自己编写这样的代码,但是这样的练习只有在你已经知道自己在做什么时才有意义。否则只需使用std::vector 及其erase 无关注意:分配和释放内存的成本很高。通常,如果您只是从数组中删除元素,您只需将删除的元素之后的剩余数组元素移回以覆盖已删除的元素,更新一点簿记以跟踪分配中元素的计数并离开仅分配本身。 Andrew.09:您说过“很遗憾,我无法更改该功能” - 但现在,您有了吗?您已经获得了原始问题的答案,因此您不应过于激进地编辑问题,以至于您获得的答案不再有意义。我已恢复您对函数签名的更改。 【参考方案1】:

不是一个好主意,但它回答了这个问题。在最初的问题中,您有注释“删除其维度”,我将其解释为您想要缩小分配的内存。示例:

#include <algorithm> // std::copy_n
#include <iostream>

int* del_element(int* vector, int dim, int el) 
    int* rv = nullptr;
    if(--dim > 0)             // must have at least 1 element
        rv = new int[dim];     // allocate new memory

        // copy the the elements before `el`:
        std::copy_n(vector, el, rv);
    
        // copy the elements after `el`:
        std::copy_n(vector + el + 1, dim - el, rv + el); 
    
    delete[] vector; // delete the old data
    return rv;       // return the new data (nullptr if empty)


int main() 
    int* v = new int[10]0,1,2,3,4,5,6,7,8,9;
    
    v = del_element(v, 10, 5); // erase the sixth element

    for(int* it = v, *end = v + 9; it != end; ++it) 
        std::cout << *it << '\n';
    

    delete[] v;

无需缩小分配的内存,您只需std::move 数据即可擦除所选元素:

int* del_element(int* vector, int dim, int el) 
    
    // move the elements after `el` one step to "the left":
    std::move(vector + el + 1, vector + dim, vector + el);
    
    return vector;

更好的方法是使用std::vector&lt;int&gt;:

#include <iostream>
#include <vector>

int main() 
    std::vector<int> v0,1,2,3,4,5,6,7,8,9;
    
    v.erase(v.begin() + 5); // erase the sixth element
    
    for(int value : v) 
        std::cout << value << '\n';
    

【讨论】:

也许可以回答这个问题。据我们所知,int* v = new int[10]0,1,2,3,4,5,6,7,8,9; 实际上是提问者代码中的int v[10] = 0,1,2,3,4,5,6,7,8,9;,答案是“你不能这样做,D00d。” @user4581301 "一个动态分配的数组" 表明它实际上是动态分配的。 我会给你那个,希望他们没有malloc这个傻瓜。 @user4581301 我也想到了这个想法:-)【参考方案2】:

这是一个糟糕的想法(或者可能是一个糟糕的学校练习)。请使用std::vector,或者在最坏的情况下使用std::array

(另外,也许不要将普通数组称为“vector”,不要将size称为dim(可能与维数混淆),不要使用int are size_t 应该是,尽可能避免使用原始指针等)

该函数应返回 std::unique_ptr&lt;int[]&gt; 以清楚地记录所有权转移。

如果您应该处理原始数组,请使用std::unique_ptr&lt;int[]&gt; 参数。如果您应该处理原始数组,请使用const int * 参数。

最重要的是,使用valgrind 仔细检查所有内容;它必须无错误地终止。

最后但同样重要的是,如果可能,不要将元素类型限制为int;你未来的自己会感谢你的。

#include <memory>

template<typename Element>
std::unique_ptr<Element[]> del_element(std::unique_ptr<Element[]> array,
                                       size_t size, size_t idx) 
  auto result = std::make_unique<Element[]>(size - 1);
  for (size_t i = 0; i < idx; ++i) result[i] = array[i];
  for (size_t i = idx + 1; i < size; ++i) result[i - 1] = array[i];
  return result;

另外,设置打印功能进行调试。

#include <iostream>

template<typename Element>
void print_array(const Element *array, size_t size) 
  std::cout << '[';
  if (size) 
    std::cout << *array;
    for (size_t i = 1; i < size; ++i) std::cout << ", " << array[i];
  
  std::cout << ']' << std::endl;

另外,别忘了测试它。 valgrind是你的朋友!

int main() 
  std::unique_ptr<int[]> first = std::make_unique<int[]>(7);
  for (size_t i = 0; i < 7; ++i) first[i] = i - 3;
  print_array(first.get(), 7);
  std::unique_ptr<int[]> second = del_element(std::move(first), 7, 3);
  print_array(second.get(), 6);
  std::unique_ptr<int[]> third = del_element(std::move(second), 6, 0);
  print_array(third.get(), 5);
  std::unique_ptr<int[]> forth = del_element(std::move(third), 5, 4);
  print_array(forth.get(), 4);
  std::unique_ptr<int[]> fifth = del_element(std::move(forth), 4, 2);
  print_array(fifth.get(), 3);
  std::unique_ptr<int[]> sixth = del_element(std::move(fifth), 3, 1);
  print_array(sixth.get(), 2);
  std::unique_ptr<int[]> seventh = del_element(std::move(sixth), 2, 0);
  print_array(seventh.get(), 1);
  std::unique_ptr<int[]> eighth = del_element(std::move(sixth), 1, 0);
  print_array(eighth.get(), 0);

最后但同样重要的是,请扔掉所有这些废话,使用std::vectorstd::dequestd::list 或任何适合您的用例。它具有更多的功能和更少的错误。

【讨论】:

是的。这是学校的练习。不幸的是,我无法更改该功能。这就是为什么它听起来有点奇怪 嗯,这肯定是一个很好的 C 学校练习,但是从原始指针开始一个 C++ 类是(恕我直言)一个坏主意。原始指针不受欢迎的原因包括(但不限于)它们对异常安全的无知和零范围意识。相比之下,基于对象的“指针”(例如 std::unique_ptr)解决了这些问题。

以上是关于删除元素后如何返回数组?的主要内容,如果未能解决你的问题,请参考以下文章

重温前端基础之-js排序算法

Array数组常用方法

VB 数组中如何根据值返回元素的位置索引值

2021-09-20:给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O

方法功能描述:从str1中删除所有的str2,并返回删除后的结果,返回结果为Object[]数组

JS查找数组指定元素