Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/138.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 从矢量中最快地擦除元素或更好地使用内存(排序基数)_C++_Stdvector_Radix Sort - Fatal编程技术网

C++ 从矢量中最快地擦除元素或更好地使用内存(排序基数)

C++ 从矢量中最快地擦除元素或更好地使用内存(排序基数),c++,stdvector,radix-sort,C++,Stdvector,Radix Sort,我遇到了一个问题,我从基数排序算法创建了一个实现,但我认为我可以使用更少的内存,而且我可以!但是我这样做是在使用后擦除向量的元素。问题是:执行时间是3分钟,而不是17秒。如何加快元素的擦除速度?或如何更好地利用记忆 排序.hpp #include <iostream> #include <vector> #include <algorithm> unsigned digits_counter(long long unsigned x); void rad

我遇到了一个问题,我从基数排序算法创建了一个实现,但我认为我可以使用更少的内存,而且我可以!但是我这样做是在使用后擦除向量的元素。问题是:执行时间是3分钟,而不是17秒。如何加快元素的擦除速度?或如何更好地利用记忆

排序.hpp

#include <iostream>

#include <vector>
#include <algorithm>

unsigned digits_counter(long long unsigned x);

void radix( std::vector<unsigned> &vec )
{
  unsigned size = vec.size();
  if(size == 0);
  else {
    unsigned int max = *max_element(vec.begin(), vec.end());
    unsigned int digits = digits_counter( max );

    // FOR EVERY 10 POWER...
    for (unsigned i = 0; i < digits; i++) {
      std::vector < std::vector <unsigned>  > base(10, std::vector <unsigned> ());

#ifdef ERASE
      // GET EVERY NUMBER IN THE VECTOR AND
      for (unsigned j = 0; j < size; j++) {
    unsigned int digit = vec[0];

    // GET THE DIGIT FROM POSITION "i" OF THE NUMBER vec[j]
    for (unsigned k = 0; k < i; k++)
      digit /= 10;
    digit %= 10;

    // AND PUSH NUMBER IN HIS BASE BUCKET
    base[ digit ].push_back( vec[0] );
    vec.erase(vec.begin());
      }

#else
      // GET EVERY NUMBER IN THE VECTOR AND
      for (unsigned j = 0; j < size; j++) {
    unsigned int digit = vec[j];

    // GET THE DIGIT FROM POSITION "i" OF THE NUMBER vec[j]
    for (unsigned k = 0; k < i; k++)
      digit /= 10;
    digit %= 10;

    // AND PUSH NUMBER IN HIS BASE BUCKET
    base[ digit ].push_back( vec[j] );
      }
      vec.erase(vec.begin(), vec.end()); 
#endif

      for (unsigned j = 0; j < 10; j++)
    for (unsigned k = 0; k < base[j].size(); k++)
      vec.push_back( base[j][k] );
    }
  }
}


void fancy_sort( std::vector <unsigned> &v ) {
  if( v.size() <= 1 )
    return;
  if( v.size() == 2 ) {
    if (v.front() >= v.back())
      std::swap(v.front(), v.back());
    return;
  }
  radix(v);
}
#include <vector>

#include "sort.hpp"

using namespace std;

int main(void)
{
  vector <unsigned> vec;

  vec.resize(rand()%10000);

  for (unsigned j = 0; j < 10000; j++) {
    for (unsigned int i = 0; i < vec.size(); i++)
      vec[i] = rand() % 100;
    fancy_sort(vec);
  }


  return 0;
}
使用擦除:

g++ -D ERASE -O3 -Wall sort.cpp && time ./a.out
./a.out  134.64s user 0.06s system 99% cpu 2:15.20 total

std::vector
不允许从中移除零件。这是你必须接受的事实。速度和内存使用之间的权衡是一个经典问题。对于载体,任何移除(从其末端移除除外)都是昂贵且浪费的。这是因为每次删除元素时,程序要么必须在内部重新分配数组,要么必须移动所有元素以填充空隙。这是一个终极限制,如果你继续使用向量,你永远无法克服

问题的向量:速度快,但占用大量内存

另一个(可能)最佳的极端(内存方面)是,在任何地方删除任何内容都绝对没有问题。另一方面,访问元素只能通过对元素的整个列表进行迭代来实现,因为它基本上是一个元素,不能通过元素的编号来访问元素

列出您的问题:最佳内存使用率,但速度较慢,因为访问列表元素的速度较慢

最后,中间立场是。它们提供了向量和列表之间的中间地带。它们在内存中不是连续的,但可以通过它们的编号找到项。从中间删除元素不一定会在向量中造成相同的破坏。了解更多关于他们的信息

为您的问题提问:根据问题的不同,中间接地可能对内存和访问都很快


如果记忆是你最关心的问题,那么一定要列出清单。这是最快的。如果你想得到最通用的解决方案,可以选择deque。另外,不要忽略将整个数组复制到另一个容器、对其进行排序,然后再将其复制回来的可能性。根据阵列的大小,这可能会有所帮助。

构建程序时使用了哪些优化?如果它是一个“调试”或未优化的构建,那么结果将毫无意义。您也没有提到正在排序的数字的数量,也没有发布。您可以尝试创建一个固定大小的std:vector,而不是对每个数字执行擦除/分配。分配和释放内存的开销可能会影响您的运行时。@PaulMcKenzie此编辑几乎完成,但您可以得到更好的主意。或者。。我可以从头到尾分类。这会更快,对吗?你说消除端点并不昂贵。@MoisesRojo如果这对你的算法有效,那么是的。但同样,您只能从末尾删除元素。否则,您将破坏性能。
g++ -D ERASE -O3 -Wall sort.cpp && time ./a.out
./a.out  134.64s user 0.06s system 99% cpu 2:15.20 total