给定一个未排序的数组,如何删除重复项然后对其进行排序?

Posted

技术标签:

【中文标题】给定一个未排序的数组,如何删除重复项然后对其进行排序?【英文标题】:Given an unsorted array, how to remove duplicates then sort it? 【发布时间】:2020-10-30 15:53:07 【问题描述】:

我遇到了麻烦,你能帮帮我吗?

我成功删除了重复项,然后我使用冒泡排序对其进行排序,但效率低下。

如何删除重复项然后对其进行排序?使用2个功能不能带来我想要的。

#include <stdio.h>
#include <conio.h>

int arr[100];
int n;
void RemoveDuplicate(int arr[]);
void Print(int arr[]);

int main()  

    int i;
    printf("Enter n:");
    scanf("%d",&n);
    for(i=0;i<n;i++)
        scanf("%d",&arr[i]);
    RemoveDuplicate(arr);
    Print(arr);
    getch();    
    return 0;


void Print(int arr[])

    int i;
    for(i=0;i<n;i++)
        printf("%d ",arr[i]);


void RemoveDuplicate(int arr[])

    int i,j,k;
   for(i=0;i<n;i++)
    
    for(j=i+1;j<n;)
        
        if(arr[i]==arr[j])
            
            for(k=j;k<n;k++)
                
                arr[k]=arr[k+1];
                
            n--;
            
        else
            j++;
        
       

【问题讨论】:

翻转操作。排序,然后删除重复项。让它更容易。 提示:通常以相反的方向进行:首先对序列进行排序,而不是删除重复项。删除未排序序列中的重复项很痛苦。 C 还是 C++?请选择一个。 您可以在排序时删除重复项。如果你进行堆排序,你可以比较从堆中弹出的项与数组的已排序部分中的前一项,如果它与前一项匹配,则丢弃新值。 在 C++ 中,您可以使用 std::set 容器来存储唯一项 【参考方案1】:

所有示例均未经测试,并以以下内容开头

if (n<1 || n > sizeof(arr))
  return;

auto begin = std::begin(arr);
auto end = begin+n;

使用 std::set

std::set<int> unique(begin, end);
std::copy(unique.begin(), unique.end(), std::begin(arr));
int size = unique.size();

使用堆

std::make_heap(begin, end);
std::sort_heap(begin, end);
auto last = std::unique(begin, end);
auto size = std::distance(begin, last);

只使用 std::sort 而不是 sort_heap

std::sort(begin, end);
auto last = std::unique(begin, end);
auto size = std::distance(begin, last);

使用堆和手动弹出

std::make_heap(std::begin(arr), std::end(arr));
auto first = begin;
auto last = end;
auto sorted = std::prev(last);
std::pop_heap(first, last--);  // initial value
while (first != last)
  std::pop_heap(first, last--);
  if (*last != *sorted && last != sorted)
    *--sorted = *last;

auto size = std::distance(sorted, end);
std::copy(sorted, end, begin); // move values to start of array

条件

last != sorted

在第一次复制之前为假,之后为真,因此可以将循环分成两部分以获得更好的性能,但分支预测器应该因此消除大多数性能问题。

如果唯一值的数量很小且分布范围很小,并且“n”很大,则使用计数数组。

std::vector 文本的字符计数示例;

std::array<int,256> count;
std::vector<char> result;
for (auto ch : text)
  count[ch]++;
for (auto idx = 0; idx < count.size(); ++idx)
  if (count[idx]) 
    result.emplace_back(idx);

如果重复的数量较大但值分散,请考虑使用 std::unordered_set 代替并在末尾排序。

std::unordered:set<int> unique(begin, end);
std::copy(unique.begin(), unique.end(), std::begin(arr));
int size = unique.size();
std::sort(begin, begin+size);

【讨论】:

以上是关于给定一个未排序的数组,如何删除重复项然后对其进行排序?的主要内容,如果未能解决你的问题,请参考以下文章

删除排序数组中的重复项

26. 删除排序数组中的重复项

从排序数组中删除重复项

删除排序数组中的重复项

删除排序数组中的重复项

删除排序数组中的重复项