【问题标题】:Removing duplicate pointers from an array of pointers to any generic type从指向任何泛型类型的指针数组中删除重复指针
【发布时间】:2014-04-04 15:03:21
【问题描述】:

是否有一种通用的方法可以从数组中删除重复指针,例如对于这样的输入:

返回这个:

不需要知道指针所指事物的类型?

【问题讨论】:

  • 非常好的问题和插图。
  • 你只想删除指针,并不关心指向的数据。因此,这就像从整数数组中删除重复的整数一样。
  • 因为您可以将指针与简单的 == 进行比较,而无需考虑它们指向的内容,这似乎很常规...您尝试过什么,您在哪里卡住了?
  • BTW +1 用于精美的图纸(并且仅适用于图纸)。
  • 该链接说“当比较两个指针时,结果取决于所指向对象在地址空间中的相对位置。如果两个指向对象或不完整类型的指针都指向同一个对象,或者两者都指向同一个数组对象的最后一个元素,它们比较相等。"

标签: c algorithm pointers


【解决方案1】:

我会做以下事情:

  • 对指针数组进行排序 — O(n lg n)
  • 遍历数组,将第一个匹配项复制到另一个数组 — O(n)

如果数组已排序,则跟踪指针是否重复非常容易:您只需保存最后复制的指针,不要复制下一个指针,直到它不同为止。

另一种简单的蛮力方法(如果您需要保留原始数组中指针的顺序)是在数组中向前搜索,用NULL 替换重复项。这具有 O(n^2) 复杂性,但您可能不关心适度的数组大小。例如:

k=0
for(i=0; i<n; i++) {
   if( myarray[i] == NULL ) {
       continue;
   }
   current = myarray[i];
   unique[k] = current;
   k++;
   for(j=i+1; j<n; j++) {
       if( current == myarray[j] ) {
           myarray[j] = NULL;
       }
   }
}

【讨论】:

  • 如果按照图纸建议的顺序需要保留的话,那就不行了。
  • 这也是我最初的想法——只是在比较 ptrs (stackoverflow.com/questions/22863406/…) 时陷入了你可以假设和不能假设的问题中——我认为可能还有其他一些我没有考虑过的方法跨度>
  • 还有许多其他方法,但我认为这是最简单的方法,如果您可以接受在结果中对指针进行排序并且不需要保留其原始顺序。
  • 我为您需要保持秩序的情况添加了一个蛮力 O(n^2) 解决方案。如果您的指针数组大小适中,您可能会决定接受它。它的优点是简单。
  • 创建一个二级数​​组非常简单,该数组包含一个带有指针的结构及其在数组中的原始顺序。二级数组先按指针排序再索引,去除重复,再按索引排序二级数组,按顺序提取指针。
【解决方案2】:

使用哈希表会有所帮助,这是一个预期情况O(N) [不是最坏情况]的解决方案。

H = Empty Hash Table

foreach ptr in Array:
    if ptr NOT present in H:
        insert ptr to H

// H now have every ptr only once

wi = 1                    // write index
for ri = 1..n:            // read index
    ptr = Array[ ri ]
    if ptr in H:
        Array[ wi ] = ptr
        remove ptr from H
        wi++

【讨论】:

  • 是的,这是一个选项 - 但不幸的是,c 没有包含哈希电池 - 我确实已经使用了 uthash,所以它是一个选项 - 我认为排序和步骤是前进的方向 - 只是要非常小心使用 ptr_cmp() 根据展开结果传递给 qsort
  • 我明白,但是,哈希表是一种太好的数据结构,无法传递:-)。 K&R C 有一个小的基本实现。这有帮助吗? linux.die.net/man/3/hsearch
  • 当然 - 我同意,我广泛使用它们 (troydhanson.github.io/uthash) - 尽管与将它们融入语法的语言(例如几乎所有其他语言)相比,它在 c 中总是有点复杂
  • 我同意哈希表是规范的解决方案,但大多数库实现(包括 POSIX hcreate()/hsearch()/hdestroy() 系列)都假定密钥是字符串。除非数组相当大,否则是否值得在明显的 O(n lg n) 甚至 O(n^2) 解决方案上付出额外的努力和复杂性是有争议的。
  • @Emmet:解决任何算法问题的方法都是找到一个适用于问题的大型实例的解决方案,即一个可以很好地随输入大小扩展的解决方案。关于 Big-O 分析的所有内容,你知道 :-) 如果我们将讨论仅限于小数组,那么就没有必要像你一样搜索算法,蛮力O(N^2)包含在您的答案中,这项工作做得很好。事实上,这可能比基于排序的解决方案更可取,因为它保持了保持指针相对顺序的要求。
猜你喜欢
  • 1970-01-01
  • 2011-09-14
  • 2010-10-22
  • 1970-01-01
  • 2012-05-12
  • 1970-01-01
  • 1970-01-01
  • 2011-08-02
  • 1970-01-01
相关资源
最近更新 更多