Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.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++ 排序向量,然后将其放入AVL树,或者直接输入,哪个更快?_C++_Performance_Sorting_Vector_Avl Tree - Fatal编程技术网

C++ 排序向量,然后将其放入AVL树,或者直接输入,哪个更快?

C++ 排序向量,然后将其放入AVL树,或者直接输入,哪个更快?,c++,performance,sorting,vector,avl-tree,C++,Performance,Sorting,Vector,Avl Tree,情况是这样的: 我有数百万,可能是数十亿的字符串,我正试图解析并放入一个排序结构中,假设我有5000000个字符串。 我正在尝试编写一个快速程序,可以将所有这些字符串从一个未排序的向量放入一个有序的数据结构中,也可以快速搜索该结构,因此AVL树的推理最终我计划使用a-z哈希表进行更快的查找,但这会在以后进行。我先把所有的字符串放到一个向量中,但它们都是杂乱无章的,未排序的,长度也不同。 我不希望在我的树中有任何重复的字符串,因此如果程序找到字符串hello和hello,它将只有一个AVL条目,并

情况是这样的:

我有数百万,可能是数十亿的字符串,我正试图解析并放入一个排序结构中,假设我有5000000个字符串。 我正在尝试编写一个快速程序,可以将所有这些字符串从一个未排序的向量放入一个有序的数据结构中,也可以快速搜索该结构,因此AVL树的推理最终我计划使用a-z哈希表进行更快的查找,但这会在以后进行。我先把所有的字符串放到一个向量中,但它们都是杂乱无章的,未排序的,长度也不同。 我不希望在我的树中有任何重复的字符串,因此如果程序找到字符串hello和hello,它将只有一个AVL条目,并且将为该字符串出现的频率增加一个整数holder

所以我的问题是:在所有单词与其他相同的单词一起排序后,首先使用多线程快速排序或其他快速方法对向量进行排序,然后将其输入AVL树会更快吗,还是将未排序向量中的所有数据放入AVL树会更快,并不断检查AVL树中是否已经存在一个单词,然后递增

因此,要按照操作顺序来描述它,这里有两种情况:

CASE A:

> Get input/parse strings
> Put strings into vector (unsorted)
> Put vector into array or linked-list
> Quicksort that array/llist
> Input that sorted array into the AVL Tree
哪种情况更快


-编辑-因此,在听到一些注释后,从一开始就将排序数组插入AVL树将是一个坏主意,这是有意义的,因为需要进行多少次旋转。直接插入AVL树似乎是一个好主意,但是当一个单词已经在树的某个地方时,有效插入的最佳方法是什么?我怎样才能确保找到它?这就是我进行排序的地方吗?

想想AVL树的平衡工作方式。如果中间值排在第一位,效果最好。对于已排序的输入,您将需要大量的重新平衡,因此预排序可能弊大于利

例如,考虑下面的AVL树来保存值1-6:

    4
   / \
  2   5
 / \   \
1   3   6
如果输入顺序是4、2、5、1、3、6,则永远不需要平衡树。相反,对于排序后的输入1、2、3、4、5、6,需要执行许多重新平衡操作:

  1     +3     2     +4     2       +5     2       +6       3
   \   --->   / \   --->   / \     --->   / \     --->     / \
    2        1   3        1   3          1   4            2   5
                               \            / \          /   / \
                                4          3   5        1   4   6
更新最初的问题是,在插入AVL树之前对数据进行排序是否会提高性能。现在,OP编辑了这个问题,转向他的具体问题


但是,当一个单词已经在树的某个地方时,高效插入的最佳方法是什么?我怎样才能确保找到它?那是我分拣的地方吗

AVL树的全部目的是高效地查找数据,所以我不理解这个问题。如何遍历二叉搜索树以查找值应该是显而易见的。为什么要为此对数据进行排序

请注意,二进制搜索树是存储密钥的良好数据结构,但它也可以管理与这些密钥相关的任意数据。在您的情况下,您希望将计数与密钥一起存储。因此,您不需要单词/字符串树,而是需要表示单词及其计数的成对字符串、整数树。对于树的顺序,只需考虑字符串关键字,即单词。 对于要插入的每个单词,请在树中查找。如果已存在,请更新字数。否则,请插入字数为1的新对


最后一个注释:C++标准库附带的映射类型通常是?使用平衡树AVL或红黑实现。通过使用此实现,您将节省大量工作和bug修复。因为C++11还有一个无序的_映射,通常总是?使用哈希表实现。

想想AVL树的平衡工作方式。如果中间值排在第一位,效果最好。对于已排序的输入,您将需要大量的重新平衡,因此预排序可能弊大于利

例如,考虑下面的AVL树来保存值1-6:

    4
   / \
  2   5
 / \   \
1   3   6
如果输入顺序是4、2、5、1、3、6,则永远不需要平衡树。相反,对于排序后的输入1、2、3、4、5、6,需要执行许多重新平衡操作:

  1     +3     2     +4     2       +5     2       +6       3
   \   --->   / \   --->   / \     --->   / \     --->     / \
    2        1   3        1   3          1   4            2   5
                               \            / \          /   / \
                                4          3   5        1   4   6
更新最初的问题是,在插入AVL树之前对数据进行排序是否会提高性能。现在,OP编辑了这个问题,转向他的具体问题


但是,当一个单词已经在树的某个地方时,高效插入的最佳方法是什么?我怎样才能确保找到它?那是我分拣的地方吗

AVL树的全部目的是高效地查找数据,所以我不理解这个问题。如何遍历二叉搜索树以查找值应该是显而易见的。为什么要为此对数据进行排序

请注意,二进制搜索树是存储密钥的良好数据结构,但它也可以管理ar 与这些密钥关联的二进制数据。在您的情况下,您希望将计数与密钥一起存储。因此,您不需要单词/字符串树,而是需要表示单词及其计数的成对字符串、整数树。对于树的顺序,只需考虑字符串关键字,即单词。 对于要插入的每个单词,请在树中查找。如果已存在,请更新字数。否则,请插入字数为1的新对


最后一个注释:C++标准库附带的映射类型通常是?使用平衡树AVL或红黑实现。通过使用此实现,您将节省大量工作和bug修复。因为C++11还有一个无序的_映射,通常总是?使用哈希表实现。

以下内容在现实世界中可能不会更快

将已排序的向量插入AVL树时,将其作为树本身插入。首先插入中间部分,然后递归插入左侧部分的中间部分和右侧部分的中间部分,依此类推。如果向量中的所有值均匀分布,则不必重新平衡树。理论上

更好的是,如果您控制内部内存或首先对其使用二进制搜索,则可以从排序的向量构建自己的树


获得客观答案的唯一方法是测试和测量。

以下内容在现实世界中可能不会更快

将已排序的向量插入AVL树时,将其作为树本身插入。首先插入中间部分,然后递归插入左侧部分的中间部分和右侧部分的中间部分,依此类推。如果向量中的所有值均匀分布,则不必重新平衡树。理论上

更好的是,如果您控制内部内存或首先对其使用二进制搜索,则可以从排序的向量构建自己的树


获得客观答案的唯一方法是测试和测量。

1-在AVL树中插入的是OLog n。排序是OnLogN,因此在插入之前进行排序会降低性能。
2-为了计数,您可以使用哈希表查找每个单词的出现次数。循环遍历所有单词,更新哈希表中每个单词的计数,然后使用哈希表在AVL树中插入这些单词,以检查是否插入了该单词,以及是否插入了该单词及其相关计数

1-在AVL树中插入为OLog n。排序是OnLogN,因此在插入之前进行排序会降低性能。
2-为了计数,您可以使用哈希表查找每个单词的出现次数。循环遍历所有单词,更新哈希表中每个单词的计数,然后使用哈希表在AVL树中插入这些单词,以检查是否插入了该单词,以及是否插入了该单词及其相关计数

我将把我的评论转换成答案

如果字符串集是预定义的,也就是说,在初始加载之后,您不会向其中添加更多字符串,那么最快的方法可能是根本不使用AVL树或任何其他树

只需将字符串加载到std::vector中,在*logN上对其排序,删除uniques std::uniq,ON,然后使用std::lower_bound OlogN进行查找


由于与AVL树具有相同的复杂性,实际上很可能会更快,因为缓存友好性增强。

我将把我的注释转换为答案

如果字符串集是预定义的,也就是说,在初始加载之后,您不会向其中添加更多字符串,那么最快的方法可能是根本不使用AVL树或任何其他树

只需将字符串加载到std::vector中,在*logN上对其排序,删除uniques std::uniq,ON,然后使用std::lower_bound OlogN进行查找


由于具有与AVL树相同的复杂性,实际上很可能会更快,因为缓存友好性增强。

但是,当单词已经在树中的某个位置时,有效插入的最佳方法是什么?我怎样才能确保找到它?那是我分拣的地方吗

当关键字=单词,值=单词索引时,为什么不使用地图


这样,无论单词何时存在,您都可以访问它,并且可以使用索引对其进行操作。但是,当单词已经在树中的某个位置时,高效插入的最佳方法是什么?我怎样才能确保找到它?那是我分拣的地方吗

当关键字=单词,值=单词索引时,为什么不使用地图


这样,无论单词何时存在,您都将获得访问权限,并且您将有索引来操作它

如果您不打算以后添加更多字符串,那么您可以只使用排序向量和二进制搜索,也称为std::lower_bound,这取决于您是否具有将排序元素添加到AVL树中的特定函数。无论如何,您必须进行基准测试,因为结果可能不直观。是否可以从解析直接插入到树中?@MatthiasB Add
直接从解析中提取字符串可能是一种选择,但将其添加到介于两者之间的向量不会增加太多时间,因此这不是真正的问题。如果需要存储这么多字符串,则应将其视为数据结构。它们可能比AVL树更适合您的需求。如果您不打算以后添加更多字符串,那么您可以使用排序向量和二进制搜索(也称为std::lower_Bound),这取决于您是否有特定的函数将排序元素添加到AVL树中。不管怎么说,您必须进行基准测试,因为结果可能不直观。这是直接从解析插入到树中的选项吗?@MatthiasB直接从解析添加可能是一个选项,但将其添加到中间的向量并不会增加太多时间,所以这不是真正的问题。如果您需要存储这么多字符串,您应该将其视为您的数据结构。它们可能比AVL树更适合您的需求。请注意,在AVL树中插入N个元素是ONLogN,因此不会增加复杂性。是的,即使在最坏的情况下,插入也完全是ONLogN。在插入到树中之前添加ONLogN步骤不会使插入成为0,这是您刚刚收支平衡的情况。请注意,在AVL树中插入N个元素是ONLogN,因此不会增加复杂性。是的,即使在最坏的情况下,插入也完全是ONLogN。在树中插入之前添加ONLogN步骤将永远不会使插入为0,在这种情况下,您只是收支平衡。