各种排序函数(摘)

 

sort的应用;

1、可以传入两个参数;

     sort(a,a+N) ,其中a是数组,a+N表示对a[0]至a[N-1]的N个数进行排序(默认从小到大排序);

2、传入三个参数;

     sort(a,a+N,cmp),第三个参数是一个函数 ;

     如果让函数从大到小排序,可以用如下算法实现;

      bool cmp(int a,int b){return a>b};

      sort(A,A+N,cmp);

分排序函数函数:partial_sort:

例如,你现有一 个包含Widget对象(Widget意为“小挂件”)的vector容器,并且你想把其中质量最好的20个Widget送给你最好的客户,那么你需做的 只是找出这20个质量最好的Widget元素,剩下的并不需关心它们的顺序。这时你需要的是部分排序(相对于全排序)

bool qualityCompare(const Widget& lhs, const Widget& rhs) 
{            

  // lhs的质量不比rhs的质量差时返回true,否则返回false

}

…

partial_sort (widgets.begin(),                          // 把质量最好的20元素            

          widgets.begin() + 20,                  // 顺序放入widgets容器中          

            widgets.end(),                                                

   qualityCompare); 

…                                                                  // 使用 widgets

 

通过调用partial_sort,容器中开始的20个元素就是你需要的质量最好的20个Widget,并按顺序排列,质量排第一的就是 widgets[0],  紧接着就是widgets[1],依次类推。这样你就可以把质量第一的Widget送给你最好的顾客,质量第二的Widget就可以送给下一个顾客。

 

如果你只是想把这20个质量最好的Widget礼物送给你最好的20位顾客,而不需要给他们一一对应,partial_sort在这里就有些显得大 材小用了。因为在这里,你只需要找出这20个元素,而不需要对它们本身进行排序。这时你需要的不是partial_sort,而是 nth_element。

nth_element排序算法

只是对一个区间进行排序,一直到你指定的第n个位置上放上正确的元素为止,也就是说,和你进行全排序和 nth_element排序相比,其共同点就是第n个位置是同一个元素。当nth_element函数运行后,在全排序中应该在位置n之后的元素不会出现 在n的前面,应该在位置n前面的元素也不会出现在n的后面。

nth_element (widgets.begin(),             // 把质量最好的20元素放在
                      widgets.begin() + 20,     // widgets容器的前面,
                       widgets.end(),                // 但并不关心这20个元素
                      qualityCompare);            //本身内部的顺序

partial_sort把前 20个元素还进行排列了,而nth_element并不关系他们内部的顺序。两个算法都实现了同样的功能:把质量最好的20个元素放在vector容器的 开始部分。

 

nth_element功能却是不少,除了让你找到无关顺序的top n个元素外,它还能找到某个范围的中值,或者找到在某个特定百分点的值。

 vector<Widget>::iterator begin(widgets.begin());     // widgets的第一个
    vector<Widget>::iterator end(widgets.end());           //和最后一个迭代器
                                                                                      // 
     vector<Widget>::iterator goalPosition;                      // 需要定位的那个迭代器

      //以下代码用来得到质量排在中间的那个元素的迭代器
    goalPosition = begin + widgets.size() / 2;             // 要找的那个元素应该
                                                                                 //在vector的中部。
    nth_element(begin, goalPosition, end,         // 找到容器widgets元素的中值
                        qualityCompare);                      //
// goalPosition现在指向中值元素 
    
     //以下代码用来得到质量排在75%的元素
    vector<Widget>::size_type goalOffset =               // 计算出要找的值
                                        0.25 * widgets.size();         //离begin迭代器的距离。 
                                                                                  // 
     nth_element( begin, begin + goalOffset, end,       // 得到质量排在75%的元素
                            qualityCompare);                           //
// goalPosition 现在指向质量排在75%的元素。

 

stable_sort

在一个“稳定”的排序算法中,如果两个元素有相同的值, 它们的相对位置在排序后也会保持不变。例如:如果在未排序时Widget A在Widget  B之前,而且都有相同的质量等级,那么“稳定”排序算法就可以保证在排序之后,Widget A仍然在Widget  B之前。而非“稳定”排序算法就不能保证这一点。

partial_sort和nth_element都不是“稳定”排序算法,真正的“稳定”排序算法是stable_sort。

 

#include <algorithm>

stable_sort,因为要对结构体排序,所以要使用该函数的三个参数的重载,例:stable_sort(vectorArray.begin(), vectorArray.end(),myCmp); 

 

 

partition算法

partition只是给你确定一个区间,把 符合特定条件的元素放到这个区间中。举例来说,要把质量等级好于等于等级2的Widget的元素放在widget容器的前端,我们可以定义一个用于识别 Widget质量等级的函数:

 bool hasAcceptableQuality(const Widget& w)
     {
         //如果w的质量等于或好于2,返回true,否则返回false
     }

然后把这个判断函数传递给partion算法:
    vector<Widget>::iterator goodEnd =   // 把所有满足hasAcceptableQuality 
                     partition(widgets.begin(),     // 条件的放在widgets容器的前面,
                    widgets.end(),                     // 返回第一个不满足条件的
                    hasAcceptableQuality);       //元素的位置

这样一来,所有在迭代器widgets.begin()和迭代器goodEnd之间的元素都是满足需求的元素:其质量等级好于或等于2。而在  goodEnd 到 widgets.end()  之间的元素的质量等级都会低于质量等级2。如果你对质量等级相同元素的相对位置很关心的话,你可以选择stable_partition算法来代替 partition。

 

总结:

若需对vector, string, deque, 或 array容器进行全排序,你可选择sort或stable_sort;

若只需对vector, string, deque, 或 array容器中取得top n的元素,部分排序partial_sort是首选.

若对于vector, string, deque, 或array容器,你需要找到第n个位置的元素或者你需要得到top n且不关系top n中的内部顺序,nth_element是最理想的;

若你需要从标准序列容器或者array中把满足某个条件或者不满足某个条件的元素分开,你最好使用partition或stable_partition;

若使用的list容器,你可以直接使用partition和stable_partition算法,你可以使用list::sort代替sort和 stable_sort排序。若你需要得到partial_sort或nth_element的排序效果,你必须间接使用。正如上面介绍的有几种方式可以 选择。

例子

#include<iostream>
 #include<vector>
 #include<iterator>
 #include<cstdlib>
 #include<algorithm> 
 #include<functional>

using namespace std;

bool less5(int a)
 {
 return a<5;
 }

int main()
 {
     const size_t n=10;
     int a[10]={3,6,9,2,5,8,1,4,7,0};
     vector<int> ive(a,a+n);
     cout<<"After sort;\n";
     sort(a,a+n);
     for(int i=0;i<n;++i) cout<<a[i]<<" ";
     cout<<endl;
     
     cout<<"The top 4 number: "<<endl;
     partial_sort(ive.begin(),ive.begin()+4,ive.end(),greater<int>());
     copy(ive.begin(),ive.begin()+4,ostream_iterator<int>(cout," "));
     
     cout<<"\nThe 4th number: "<<endl;
     nth_element(ive.begin(),ive.begin()+3,ive.end(),greater<int>());   //注意是 ive.begin()+3
     cout<<ive[3];
     
     cout<<"\nThe top 4 number: "<<endl;
     copy(ive.begin(),ive.begin()+4,ostream_iterator<int>(cout," "));
     
     cout<<"\nThe numbers are divided less or greater 5:"<<endl;
     partition(ive.begin(),ive.end(),less5);
     copy(ive.begin(),ive.end(),ostream_iterator<int>(cout," "));
     cout<<endl;
     
     system("pause");
     return 0;
 }

 

posted @ 2016-05-10 21:50  Not-Bad  阅读(1129)  评论(0编辑  收藏  举报