C++数组排序、容器排序和多级排序的若干方法总结
发现随笔数量对不上查看了一下草稿箱,果然有个古早的坑没有填。现在来看都是入门级问题了,不过还是补一下欠的债(笑)
---------------------------------更新线---------------------------------
1、自动二分lower_bound和upper_bound
lower找第一个大于等于的位置,upper找第一个大于的位置;
反过来需要多加一个greater<int>;不过要注意,此类内置函数和sort一样是需要加(),而STL容器的自定义结构体函数那里是必须不加,如:multiset< int,greater<int> > num_set;
值域:(0,len),有(len+1)种取值。
1 vector<int> vec; 2 vec.pb(10); 3 vec.pb(20); 4 vec.pb(30); 5 int pos1=upper_bound(vec.begin(),vec.end(),0,greater<int>())-vec.begin(); 6 int pos2=lower_bound(vec.begin(),vec.end(),0)-vec.begin(); 7 cout<<pos1<<endl; 8 cout<<pos2<<endl;
1 int vec[3]={1,2,3}; 2 int pos1=upper_bound(vec,vec+3,10)-vec;
容器或者数组都行。
2、find函数
一样的,找容器或者数组中是否存在某个数值。但是需要注意find是对任意序列进行顺序遍历,时间复杂度 O(n),不要求数据有序。内置二分算法的查找是binary_search,仅适用于已排序范围,时间复杂度O(log n) 。可能比自己手写的二分快点常数。
1 vector<int> vec; 2 vec.pb(10); 3 vec.pb(20); 4 vec.pb(30); 5 int pos1=find(vec.begin(),vec.end(),0,greater<int>())-vec.begin(); 6 int pos2=find(vec.begin(),vec.end(),0)-vec.begin(); 7 cout<<pos1<<endl; 8 cout<<pos2<<endl;
1 int vec[3]={1,2,3};
2 int pos1=find(vec,vec+3,10)-vec;
3、结构体多级排序
基本数据类型就像之前讲的那样构造multiset< int,greater<int> > num_set就可以了,自定义数据结构或者多级排序就需要增加外置比较函数或者内置重载运算符。
1 struct Person { 2 string name; 3 int age; 4 float height; 5 }; 6 7 bool compare(const Person& a, const Person& b) { 8 return tie(a.age, a.height, a.name) < tie(b.age, b.height, b.name); 9 } 10 11 int main() { 12 vector<Person> people = { 13 {"Alice", 30, 5.5}, 14 {"Bob", 25, 5.9}, 15 {"Charlie", 30, 5.8}, 16 {"David", 25, 5.6} 17 }; 18 19 sort(people.begin(), people.end(), compare); 20 21 for (const auto& person : people) { 22 cout << person.name << " " << person.age << " " << person.height << endl; 23 } 24 25 return 0; 26 }
运算符重载方式如下。重载完直接sort即可。
1 struct Person { 2 string name; 3 int age; 4 float height; 5 6 // 重载<运算符 7 bool operator<(const Person& other) const { 8 if (age != other.age) { 9 return age < other.age; 10 } else { 11 return height < other.height; 12 } 13 } 14 };
其实也可以通过友元函数的方式进行编写,友元的作用在于提高程序的运行效率,但是,它破坏了类的封装性和隐藏性,使得非成员函数可以访问类的私有成员。现在来看只适用于算法竞赛(写起来也没快多少),在大型项目的编写中不应使用。friend 本质上开了个后门,且这个后门不经过任何成员函数的逻辑校验(比如边界检查、状态同步、日志记录)。
上述方法都是通用方法,C++后期版本提供了tie,用于解构tuple的多级比较,不推荐,但是写出来显得很装。
1 sort(people.begin(), people.end(), [](const Person& a, const Person& b) { 2 return tie(a.age, a.height) < tie(b.age, b.height); 3 });

浙公网安备 33010602011771号