删除重复项算法
Remove duplicates algorithm
我正在尝试编写一个算法来从vector<struct xxxx*>
中删除重复项。
struct xxxx{
int value; // This is just to make you understand
xxxx* one;
xxxx* two;
}
就像你看到的结构体,它就像一个树,但是指针不是有序的。指针可以指向其他指针中的任何一个(实际上不是任何一个,而是大多数)。并且vector不包含结构体而是包含指针,所以我也不能使用std算法来帮助我。
我试图删除具有完全相同的值和相同的两个指针的重复项,但同时,如果我有两个类似的结构体(让我们说A
和B
)和C.one
或C.two
指向B
。然后我需要将其更改为A
,反之亦然。
换句话说:如果A == B
,则删除B
并将C.one
更改为A
。
我想我可以写蛮力,所以如果没有更好的算法我就自己写了
昨天,我试图向一位同事解释一个非常类似的问题的合理方法,他使用了N方的解决方案来解决N log N的问题。
首先创建一个helper结构,它基本上是一个xxxx*的包装器,带有检查内容(不是指针值)的比较操作符,可能还有一些其他实用函数。与只使用xxxx*相比,这个包装器结构不是严格需要的,但从经验来看,我认为它使任务更简洁。
创建一个std::帮助结构的集合,你只能在其中插入唯一的元素,并可能在另一个集合中插入递归无法解析的元素。
循环遍历原始向量,并在每个位置递归遍历它的子向量。如果你命中了唯一集中已经存在的子指针,那就是那个子指针的最终值。如果你命中了匹配唯一元素的子元素,而不是它所匹配的元素,那么修复让你到达那里的指针。如果还存在空指针的可能性,它应该在递归底部,并且如果可能存在循环,则需要检测它们(使用递归未解析的集合)并决定如何处理循环。在某一时刻,你会遇到已解析的唯一元素,并将其添加到唯一集合中。
这个想法的表现,甚至可能是合理的,取决于循环的深度和复杂性,以及你想用循环做什么。在一些混乱的情况下,一个循环会映射到另一个循环,但检测这种情况可能非常棘手。如果你的阶段"像树一样"意味着"没有循环",那么递归就会干净而有效地结束,而不需要显式管理递归未解析元素的额外复杂性。
显然,我省略了一些繁琐的工作细节,比如当你退出递归时检测唯一/非唯一,以及当你在递归上面的主循环中碰到一个项时检测"在早期递归中已经做过了"。但是,在编写代码的相关部分时,所有这些细节都应该非常明显。
编辑:要理解尽管在顺序循环中嵌套了递归,但仍然有很少的节点访问,请从指针的角度考虑。我们最多跟踪每个指针一次(有些重复项在不跟踪指针的情况下被预先检测到)。对于N个节点,有N个顶层指针(如果我理解正确的话)和明显少于2N个内部指针(越像树,越接近N-1个内部指针,而不是2N个)。所以每个节点的平均访问次数少于3次,其中少数访问需要预查找和后递归查找,每次查找是log U, U是到该点为止找到的唯一项的数量。所以我们可以看到6 N log N
的边界
- 将数组的地址分配给变量并删除
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- C/C++编译器通常会删除重复的库吗
- 为什么这个运算符<重载函数对 STL 算法不可见?
- 高效的字符串截断算法,按顺序删除相等的前缀和后缀
- 数组 X[n] 仅存储名称.编写算法以在数组中插入或删除 ITEM
- 用于删除符号并生成排列的算法
- 删除模板/类型名后算法变慢C++
- 编写递归算法以从链表中删除元素.编写递归算法以将元素添加到链表中
- C bST删除节点会破坏排序算法
- 删除元素的算法
- 如何从未排序的 std::vector 中删除重复项,同时使用算法保持原始排序
- 删除 2 个给定索引之间的元素的最佳算法
- 从数组中删除重复项的算法不起作用
- 在字符串算法中删除重复项
- STL算法删除容器中的所有对象
- 删除重复项算法
- 红黑树删除算法(CLR第三版)
- 何时删除卡拉苏巴算法中分配的内存?
- 动态图算法的实现,该算法在删除边后保留图的连接分量的数量