• C++
  • C++ 排序+去重 零基础完整教程

  • @ 2026-8-10 15:20:53

C++ 排序+去重 零基础完整教程

核心组合:sort()排序 + unique()去重 + erase()删除重复残余元素 适用:数组、vector容器,竞赛GESP/CSP高频考点

原理简单讲

  1. sort:把容器从小到大排好序,unique只能去掉相邻重复元素,所以必须先排序
  2. unique:把重复元素挪到容器末尾,返回重复段的起始迭代器,不会真正删除,只是移动
  3. erase:根据unique返回的位置,真正删掉后面重复的部分

⚠️重点:不去排序直接调用unique,完全无效!

头文件必备

#include <iostream>
#include <vector>
#include <algorithm> // sort、unique都在这个头文件
using namespace std;

示例1:vector 完整排序去重(最常用,竞赛首选)

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main()
{
    // 定义vector,有很多重复数字
    vector<int> v = {5, 2, 8, 2, 5, 1, 8, 3, 1};

    cout << "原始数据:";
    for(int i = 0; i < v.size(); i++)
    {
        cout << v[i] << " ";
    }
    cout << endl;

    // 第一步:排序 sort(起始迭代器,结束迭代器)
    sort(v.begin(), v.end());
    cout << "排序之后:";
    for(int i = 0; i < v.size(); i++)
    {
        cout << v[i] << " ";
    }
    cout << endl;

    // 第二步:unique,将重复元素移到后面,返回重复元素第一个位置
    auto pos = unique(v.begin(), v.end());

    // 第三步erase:删除pos到末尾所有重复垃圾数据
    v.erase(pos, v.end());

    cout << "排序去重完成:";
    for(int i = 0; i < v.size(); i++)
    {
        cout << v[i] << " ";
    }
    cout << endl;

    return 0;
}

运行输出

原始数据:5 2 8 2 5 1 8 3 1 
排序之后:1 2 2 3 5 5 8 8 
排序去重完成:1 2 3 5 8 

逐行解释关键语句

  1. sort(v.begin(),v.end())
  • v.begin():容器第一个元素的位置
  • v.end():容器最后一个元素下一个位置
  • 默认从小到大升序;想要降序:sort(v.begin(),v.end(),greater<int>());
  1. auto pos = unique(v.begin(),v.end()); auto自动识别迭代器类型,pos保存重复段开头位置。

unique不会改变容器大小,只是把不重复元素往前覆盖。

  1. v.erase(pos, v.end()); 从pos这个位置,一直删到末尾,真正删掉重复的残余。

示例2:普通数组排序去重(静态数组)

数组没有erase,unique返回指针,返回值是去重后有效数据的下一位指针,我们用这个指针计算新长度。

#include <iostream>
#include <algorithm>
using namespace std;

int main()
{
    int a[100] = {5,2,8,2,5,1,8,3,1};
    int n = 9; // 当前数组有效元素个数

    sort(a, a+n); //数组sort:首地址,首地址+有效个数

    // unique返回去重后末尾的指针
    int *p = unique(a, a+n);
    //计算去重之后新的元素数量
    int new_len = p - a;

    cout << "数组去重后:";
    for(int i=0; i<new_len; i++)
    {
        cout << a[i] << " ";
    }
    return 0;
}

输出:1 2 3 5 8

数组本身内存不会缩小,只用new_len当做有效长度访问。

示例3:输入若干数字,排序去重(GESP真题风格完整代码)

输入:第一行n,第二行n个整数,输出去重升序结果

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main()
{
    int n;
    cin >> n;
    vector<int> arr(n);
    for(int i = 0; i < n; i++)
    {
        cin >> arr[i];
    }

    sort(arr.begin(), arr.end());
    auto last = unique(arr.begin(), arr.end());
    arr.erase(last, arr.end());

    //输出结果
    for(int i = 0; i < arr.size(); i++)
    {
        if(i>0) cout << " ";
        cout << arr[i];
    }
    cout << endl;
    return 0;
}

输入:

9
5 2 8 2 5 1 8 3 1

输出:

1 2 3 5 8

常见坑点(考试必看)

  1. ❌不排序直接unique:完全无效!重复的元素不挨在一起,unique识别不出。
//错误写法
unique(v.begin(),v.end());
v.erase(...)
  1. ❌erase参数写错:erase(v.end(), pos)顺序颠倒,程序直接崩溃。

永远:erase(起点,终点),起点在前,终点在后。

  1. ❌数组忘记传入有效长度:sort(a,a+100)会把数组后面大量0参与排序。
  2. ❌unique之后还继续使用原来size(),vector大小还没变小,要erase之后size才更新。

常用变体

1.降序排序再去重

sort(v.begin(),v.end(),greater<int>());
auto pos = unique(v.begin(),v.end());
v.erase(pos,v.end());

2.字符串排序去重

string s = "abacaba";
sort(s.begin(),s.end());
auto p = unique(s.begin(),s.end());
s.erase(p,s.end());
cout << s; //abc

速记模板(考试直接默写vector版本)

sort(v.begin(), v.end());
auto it = unique(v.begin(), v.end());
v.erase(it, v.end());

0 条评论

目前还没有评论...