【问题标题】:What is better in my case: vector or list?在我的情况下哪个更好:向量还是列表?
【发布时间】:2014-12-04 15:50:09
【问题描述】:

我有一个读取文件夹中文件的函数(为此我使用了 boost)。我也试图只保留 2 个文件(它们是日志文件,所以它们被轮换,我不想在第三个文件中保留旧日志 = 日志)。我将文件名存储在一个列表中,但由于读取不是按创建时间顺序完成的,我需要对列表进行排序。

我知道

向量擅长:

  • 通过位置索引(恒定时间)访问各个元素。
  • 以任何顺序(线性时间)迭代元素。
  • 从其末尾添加和删除元素(恒定摊销时间)。

列出容器的优点:

  • 在容器中的任何位置高效插入和移除元素 (恒定时间)。
  • 容器内甚至不同容器之间的高效移动元素和元素块(恒定时间)。
  • 以正向或反向顺序(线性时间)迭代元素。

我不确定最好的方法是什么:使用列表还是向量?

我可以

  • 使用向量并按升序排序、从末尾删除、添加新元素(在末尾)、重新排序等; 或
  • 使用列表并升序排序,从头删除,在末尾添加新元素,度假村等;

  • 是否只需要在开头进行排序,因为我插入的每个文件名都是最后创建的?
  • 如果列表/向量已经排序,那么什么时候重新排序呢?
  • 如果我使用std::is_sorted 可以不每次都排序吗?

更多信息:

因为boost的文件轮换没有“remove file if too many”的状态,只有“磁盘上有足够的空间”,所以我实现了保留最后两个文件的这一步,或者每次a都删除最旧的文件新的一个被创建并且有 2 个日志文件。因此,每次创建新的日志文件时,我都会验证文件列表,如果有足够的(2 个或更多),只需删除旧的。因为文件名是logs_%N.log,所以我不知道文件logs_X1.log是否早于logs_X2.log

eg:我重新启动应用程序,有logs_51.log、logs_52.log文件,要删除哪一个?假设它要删除logs_51.log并创建logs_0.log,如果我重新启动它,就会有logs_52.log和logs_0.log。现在要删除哪一个?)

这就是我需要排序的原因,因为应用程序可能会重新启动,并且我会读取现有文件,完成具有更多空间的文件,然后创建一个新文件。

【问题讨论】:

  • 如果只有两个文件,排序的目的是什么,甚至根本就没有容器?
  • 我说差异并不重要,不必担心。您正在优化一些花费很少时间的东西。而且它不像你会在一个循环中调用数十亿次。
  • use vector and sort it ascending, delete from the end, add new element (at the end), reorder, etc 毫无意义。在开头插入比在结尾插入和排序要快得多。
  • @user2079303 不确定该建议来自何处 - 在 vector 末尾插入通常更快,因为它避免了将项目随机排列。
  • @sop 好的,所以您实际上是在谈论 2 元素容器!您在这里询问的任何选择都不会产生任何影响。

标签: c++ list sorting vector


【解决方案1】:

对于这种特殊情况,容器将有大约 2 个元素,一点点都没有关系。枚举文件和删除它们所花费的时间将比您选择的算法和数据结构慢几个数量级。只需将文件名放在std::vector 中,使用std::sort(它将对您的日志文件名进行排序,以便最早的文件名在前),然后删除前 N-2 个项目。任务完成。

但对于一些一般性建议:

这些天来,一般的建议似乎是 std::vectorstd::list 更好,即使在很多事情上 std::list 似乎也有好处,主要是因为它是更多缓存的连续存储 -友好。

可以构建显示std::list 更快的基准测试,但如果您选择std::vector 进行所有测试,您不会出错!

如果您需要随着时间的推移维护容器并且始终需要能够移除最小/最大元素,std::priority_queue 可能是个好主意。

如果您需要在容器中找到 N 个最小/最大的项目,std::partial_sort 是一种算法;它会比完整的std::sort 更快,因为它不会浪费精力对您不关心的元素进行排序。

但与所有此类一般性能问题一样,唯一正确的答案恐怕是“试试看”!

编辑:我最初建议boost::circular_buffer,因为这听起来像问题,但现在很明显这不是一个好建议,因为排序需要通过排序而不是插入顺序来创建。

【讨论】:

  • 可以排序吗?创建时需要排序
  • 我已经阅读了你的新 cmets 和更新的问题,看起来 boost::circular_buffer 实际上不是你要找的 - 我会更新我的答案。如果您正在寻找始终排序的容器,std::priority_queue 可能更合适。但实际上,我个人会通过将文件名放在std::vector 中来实现这一点,用std::sort 对其进行排序,然后遍历前N-2 个项目并删除它们;任务完成。我向您保证,文件的枚举和删除将比您选择的数据结构慢很多数量级。
  • 另外......说真的,不要为这个问题而烦恼,但是如果你遇到需要从容器中挑选N个最小/最大的项目并且你需要这样做的情况很快,算法可能是std::partial_sort - 它不会浪费时间对不需要排序的容器部分进行排序。老实说,虽然对于这个问题,它的麻烦多于它的价值。
【解决方案2】:

这里真的没有,这家伙需要比较 2 个文件的名称,而不是数据结构课程

使用 string::compare 比较文件,是的,它也会比较日志文件末尾的这些数字,所以不用担心

这是它的工作原理

 value=String.Compare(filenameA,filenameB)



  If value<0 then print("filenameA is smaller than filenameB")
  If value>0  then print("a is bigger than b") 
  If value=0  then print("a equals b")

哦,关于数据结构的选择,你不需要关心效率,或者性能问题 我的意思是您只是按名称索引 2 个文件,一个简单而不起眼的数组就可以解决问题

这里有一个如何做的例子

putNewFileMethod(FileType* arrayofFiles,FileType MynewFile)`
{



String nameOfFile0=arrayOfFiles[0].method_that_retrieves_the_filename();
String nameOfFile1=arrayOfFiles[1].method_that_retrieves_the_filename();//you can search for a method of this kind in the docs of the api you are using,`

int value=String.Compare(nameOfFile0,nameOfFile1);

      If( value<0)
        arrayOfFiles[0]=MynewFile;
else    arratOfFiles[1]=MynewFile;


}

补充说明:

您可以使用 2 个位置的圆形数组,这不需要对文件进行排序,但是您提到了有关重新启动应用程序的内容,所以我想这对您来说不是最佳解决方案, (如果您想要一个圆形数组/缓冲区示例,请告诉我)

数据结构没有内置排序功能,至少大部分没有,所以你只需要自己做一个

【讨论】:

  • 如果你出于某种原因想要通过在日志文件标题上添加随机格式来让你的生活更艰难,比如 log_iLikeRandomNames.log 试试这个日期检索方法,它通过路径工作,所以你不必提供一个文件对象 [link]msdn.microsoft.com/en-us/library/…
  • 好话。实际上我已经使用了 Boost 和 last_write_time() 函数,我会发布我的方法。关于你的回答,我不太同意字符串比较,我最后添加的例子就是原因
【解决方案3】:

其实我是用Boost来按照上次修改的方式对文件进行排序的:

bool Logger::compareAccessTime(const std::string& path1In, const std::string& path2In)
{
    return (fs::last_write_time(fs::path(path1In)) < fs::last_write_time(fs::path(path2In)));
}

在哪里fs = boost::filesystem

因为我使用了字符串列表,所以我没有更改整个代码,而是在初始化列表时添加了list::sort(compareAccessTime)。我只在应用程序的开头需要它,因为我在末尾添加并从开头删除。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-09-26
    • 2012-06-19
    • 2020-12-26
    • 2012-07-17
    • 2017-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多