it编程 > 编程语言 > C/C++

C++数组去重十种方法

45人参与 2025-03-16 C/C++

在c++中,数组去重是一个常见的操作,以下是一些常见的数组去重方法:

一、使用std::sort和std::unique(stl方法)

原理

示例代码:

#include <iostream>
#include <algorithm>
int main() {
    int arr[] = {5, 3, 4, 3, 2, 5}; 
    int n = sizeof(arr)/sizeof(arr[0]); 
    std::sort(arr, arr + n); 
    int new_end = std::unique(arr, arr + n)-arr; 
    for (int i = 0; i < new_end; i++) {
        std::cout << arr[i] << " "; 
    }
    return 0; 
}

在这个示例中,首先计算数组的大小,然后对数组进行排序,接着使用std::unique去重,最后遍历去重后的数组部分并输出。

注意事项

二、使用std::set容器

原理

std::set是c++ stl中的关联容器,它的特性是元素唯一。当向std::set中插入元素时,它会自动检查元素是否已经存在,如果不存在则插入,否则忽略。

示例代码:

#include <iostream>
#include <set>
int main() {
    int arr[] = {5, 3, 4, 3, 2, 5}; 
    int n = sizeof(arr)/sizeof(arr[0]); 
    std::set<int> s; 
    for (int i = 0; i < n; i++) {
        s.insert(arr[i]);  
    }
    for (auto it = s.begin();  it!= s.end();  it++) {
        std::cout << *it << " "; 
    }
    return 0; 
}

这里首先创建一个std::set,然后遍历数组将元素插入到std::set中,最后遍历std::set输出去重后的元素。

注意事项

三、手动比较法(双循环法)

原理

这种方法使用两层循环。外层循环遍历数组的每个元素,内层循环用于比较当前元素与之前已经处理过的元素是否相同。如果找到相同的元素,则说明当前元素是重复的,可以跳过或者进行相应的处理。

示例代码:

#include <iostream>
int main() {
    int arr[] = {5, 3, 4, 3, 2, 5}; 
    int n = sizeof(arr)/sizeof(arr[0]); 
    int new_size = 0; 
    for (int i = 0; i < n; i++) {
        bool is_duplicate = false; 
        for (int j = 0; j < new_size; j++) {
            if (arr[i] == arr[j]) {
                is_duplicate = true; 
                break; 
            }
        }
        if (!is_duplicate) {
            arr[new_size] = arr[i]; 
            new_size++; 
        }
    }
    for (int i = 0; i < new_size; i++) {
        std::cout << arr[i] << " "; 
    }
    return 0; 
}

在这个示例中,new_size用于记录去重后的数组大小。外层循环每次取一个元素,内层循环检查该元素是否已经在前面出现过,如果没有则将其放入去重后的数组部分。

注意事项

四、利用std::map记录元素出现次数

原理

std::map是c++ stl中的关联容器,它以键 - 值对的形式存储数据。在这里,可以将数组元素作为键,元素出现的次数作为值。在遍历数组时,如果元素第一次出现,则将其插入std::map中,值设为1;如果元素已经存在,则将对应的值加1。最后,只遍历值为1的键,即为去重后的元素。

示例代码:

#include <iostream>
#include <map>
int main() {
    int arr[] = {5, 3, 4, 3, 2, 5}; 
    int n = sizeof(arr)/sizeof(arr[0]); 
    std::map<int, int> m; 
    for (int i = 0; i < n; i++) {
        if (m.find(arr[i])!=  m.end())  { 
            m[arr[i]]++; 
        } else {
            m[arr[i]] = 1; 
        }
    }
    for (auto it = m.begin();  it!= m.end();  it++) {
        if (it->second == 1) {
            std::cout << it->first << " "; 
        }
    }
    return 0; 
}

首先创建std::map,然后遍历数组更新元素的出现次数,最后遍历std::map输出只出现一次的元素。

注意事项

五、使用std::unordered_set(哈希表去重)

原理

std::unordered_set是基于哈希表实现的关联容器。它的插入和查找操作平均时间复杂度接近常数时间o(1)o(1)。当向std::unordered_set中插入元素时,它会根据元素的哈希值快速判断元素是否已经存在,如果不存在则插入,从而实现去重。

示例代码:

#include <iostream>
#include <unordered_set>
int main() {
    int arr[] = {5, 3, 4, 3, 2, 5}; 
    int n = sizeof(arr)/sizeof(arr[0]); 
    std::unordered_set<int> s; 
    for (int i = 0; i < n; i++) {
        s.insert(arr[i]);  
    }
    for (auto it = s.begin();  it!= s.end();  it++) {
        std::cout << *it << " "; 
    }
    return 0; 
}

与使用std::set类似,只是这里使用的是std::unordered_set,它在性能上可能更适合一些不需要排序且元素数量较多的情况。

注意事项

六、标记法

原理

可以创建一个额外的布尔类型数组来标记已经出现过的元素。遍历原始数组时,对于每个元素,检查其在标记数组中的对应位置是否已经被标记。如果没有被标记,则说明该元素是第一次出现,将其加入去重后的结果中,并在标记数组中标记该元素;如果已经被标记,则说明是重复元素,跳过。

示例代码:

#include <iostream>
int main() {
    int arr[] = {5, 3, 4, 3, 2, 5}; 
    int n = sizeof(arr)/sizeof(arr[0]); 
    bool marked[n]; 
    for (int i = 0; i < n; i++) {
        marked[i] = false; 
    }
    int new_size = 0; 
    for (int i = 0; i < n; i++) {
        if (!marked[i]) {
            arr[new_size] = arr[i]; 
            new_size++; 
            for (int j = i + 1; j < n; j++) {
                if (arr[i] == arr[j]) { 
                    marked[j] = true; 
                }
            }
        } 
    }
    for (int i = 0; i < new_size; i++) {
        std::cout << arr[i] << " "; 
    }
    return 0; 
}

这里首先初始化标记数组,然后在遍历原始数组时,根据标记数组判断元素是否重复,并更新标记数组和去重后的数组。

注意事项

七、排序后单循环比较(优化双循环法)

原理

先对数组进行排序,这样相同的元素就会相邻。然后只需要一次循环遍历数组,比较当前元素和下一个元素是否相同。如果不同,则说明当前元素是不重复的,可以进行相应处理;如果相同,则说明是重复元素,可以跳过。

示例代码:

#include <iostream>
#include <algorithm>
int main() {
    int arr[] = {5, 3, 4, 3, 2, 5}; 
    int n = sizeof(arr)/sizeof(arr[0]); 
    std::sort(arr, arr + n); 
    int new_size = 0; 
    for (int i = 0; i < n - 1; i++) {
        if (arr[i]!= arr[i + 1]) {
            arr[new_size] = arr[i]; 
            new_size++; 
        }
    }
    arr[new_size] = arr[n - 1]; 
    new_size++; 
    for (int i = 0; i < new_size; i++) {
        std::cout << arr[i] << " "; 
    }
    return 0; 
}

先对数组排序,然后在循环中比较相邻元素,最后将最后一个元素处理并输出去重后的数组。

注意事项

八、利用数组指针和动态内存分配

原理

可以创建一个动态分配内存的新数组,然后通过指针遍历原始数组。对于原始数组中的每个元素,检查它是否已经存在于新数组中。如果不存在,则将其添加到新数组中。这种方法可以避免使用一些复杂的stl容器,但需要手动管理内存。

示例代码:

#include <iostream>
int main() {
    int arr[] = {5, 3, 4, 3, 2, 5}; 
    int n = sizeof(arr)/sizeof(arr[0]); 
    int* new_arr = new int[n]; 
    int new_size = 0; 
    for (int i = 0; i < n; i++) {
        bool is_duplicate = false; 
        for (int j = 0; j < new_size; j++) {
            if (arr[i] == new_arr[j]) { 
                is_duplicate = true; 
                break; 
            }
        }
        if (!is_duplicate) {
            new_arr[new_size] = arr[i]; 
            new_size++; 
        }
    }
    for (int i = 0; i < new_size; i++) {
        std::cout << new_arr[i] << " "; 
    }
    delete[] new_arr; 
    return 0; 
}

这里动态分配了一个新数组,然后通过双循环比较将不重复的元素放入新数组,最后输出并释放内存。

注意事项

九、使用std::vector和std::erase - std::remove组合(针对std::vector类型数组)

原理

在c++中,std::vector是一个动态数组容器。std::remove函数实际上并不会真正删除元素,而是将不想要的元素移到容器的末尾,并返回一个指向新的逻辑末尾的迭代器。然后std::erase函数根据这个迭代器真正地从std::vector中删除元素。

示例代码:

#include <iostream>
#include <vector>
#include <algorithm>
int main() {
    std::vector<int> v = {5, 3, 4, 3, 2, 5}; 
    v.erase(std::remove(v.begin(),  v.end(),  3), v.end());  
    v.erase(std::remove(v.begin(),  v.end(),  5), v.end());  
    for (auto it : v) {
        std::cout << it << " "; 
    }
    return 0; 
}

这里先使用std::remove将指定元素(这里是3和5)移到std::vector的末尾,然后使用std::erase删除这些元素。需要注意的是,如果要去重所有元素,可能需要多次调用std::removestd::erase或者采用更复杂的逻辑。

注意事项

十、自定义哈希函数去重(针对自定义类型数组)

原理

当数组中的元素是自定义类型时,可以定义一个哈希函数来计算元素的哈希值。然后可以使用类似于std::unordered_set的原理,创建一个基于自定义哈希函数的容器或者数据结构,通过比较哈希值来判断元素是否重复。

示例代码(假设自定义类型为mytype:

#include <iostream>
#include <unordered_set>
struct mytype {
    int a; 
    int b; 
    // 假设根据a和b计算哈希值
    size_t operator()(const mytype& obj) const {
        return std::hash<int>()(obj.a)^ std::hash<int>()(obj.b); 
    }
}; 
int main() {
    mytype arr[] = { {1, 2}, {3, 4}, {1, 2}, {5, 6} }; 
    int n = sizeof(arr)/sizeof(arr[0]); 
    std::unordered_set<mytype, mytype> s; 
    for (int i = 0; i < n; i++) {
        s.insert(arr[i]);  
    }
    for (auto it = s.begin();  it!= s.end();  it++) {
        std::cout << "(" << it->a << ", " << it->b << ") "; 
    }
    return 0; 
}

这里定义了mytype结构体,并为其定义了一个哈希函数。然后使用std::unordered_set结合自定义哈希函数对mytype类型的数组进行去重。

到此这篇关于c++数组去重十种方法的文章就介绍到这了,更多相关c++数组去重内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

您想发表意见!!点此发布评论

推荐阅读

Qt把文件夹从A移动到B的实现示例

03-16

Qt 智能指针的具体使用

03-16

QT移植到RK3568开发板的方法步骤

03-16

C++记录程序运行时间的四种方法

03-17

C/C++随机数生成的五种方法

03-17

VSCode中C/C++编码乱码问题的两种解决方法

03-17

猜你喜欢

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论