stl中的排序(2) sort/stable_sort

C++中sort和stable_sort的区别

  1. sort是快速排序实现,因此是不稳定的;stable_sort是归并排序实现,因此是稳定的;
  2. 对于相等的元素sort可能改变顺序,stable_sort保证排序后相等的元素次序不变;

Compare函数

分析源码,确定compare函数的用法

sort函数的两个重载:

template <class RandomAccessIterator>
inline void sort(RandomAccessIterator first, RandomAccessIterator last) {
  if (first != last) {
    __introsort_loop(first, last, value_type(first), __lg(last - first) * 2);
    __final_insertion_sort(first, last);
  }
}

template <class RandomAccessIterator, class Compare>
inline void sort(RandomAccessIterator first, RandomAccessIterator last,
                 Compare comp) {
  if (first != last) {
    __introsort_loop(first, last, value_type(first), __lg(last - first) * 2,
                     comp);
    __final_insertion_sort(first, last, comp);
  }
}

sort函数底层的一段源码:

template <class RandomAccessIterator, class T>
void __partial_sort(RandomAccessIterator first, RandomAccessIterator middle,
                    RandomAccessIterator last, T*) {
  make_heap(first, middle);
  for (RandomAccessIterator i = middle; i < last; ++i)
    if (*i < *first) 
      __pop_heap(first, middle, i, T(*i), distance_type(first));
  sort_heap(first, middle);
}

template <class RandomAccessIterator, class T, class Compare>
void __partial_sort(RandomAccessIterator first, RandomAccessIterator middle,
                    RandomAccessIterator last, T*, Compare comp) {
  make_heap(first, middle, comp);
  for (RandomAccessIterator i = middle; i < last; ++i)
    if (comp(*i, *first))
      __pop_heap(first, middle, i, T(*i), comp, distance_type(first));
  sort_heap(first, middle, comp);
}

从以上源码可以看出来

  1. sort的compare函数可以通过函数传参的方式传入
// struct less的仿函数
template <class T>
struct compare1 {
    bool operator()(const T& x, const T& y) const { return x < y; }
};

// 或者
template <class T>
bool compare2(const T& x, const T& y) const { return x < y; }

*注意使用时的区别,compare1是一个struct类型,compare1()是一个struct compare1的对象。
而compare2是一个函数指针对象,而他的类型是bool (const T& x, const T& y)。

举个栗子:

	std::vector<int> vector_test;
// 第一种写法
	std::sort(vector_test.begin(), vector_test.end(), compare2<int>);
	// 等价于
	std::sort<std::vector<int>::iterator, bool(const int& a, const int& b)>(vector_test.begin(), vector_test.end(), compare2<int>);
	std::sort<std::vector<int>::iterator, bool(*)(const int& a, const int& b)>(vector_test.begin(), vector_test.end(), compare2<int>);
	// 等价于
	std::sort<std::vector<int>::iterator, decltype(compare2<int>)>(vector_test.begin(), vector_test.end(), compare2<int>);

	std::sort<std::vector<int>::iterator, bool(&)(const int& a, const int& b)>(vector_test.begin(), vector_test.end(), compare2<int>); // build error
// 第二种写法
	std::sort(vector_test.begin(), vector_test.end(), compare1<int>());
	等价于
	std::sort<std::vector<int>::iterator, compare1<int>>(vector_test.begin(), vector_test.end(), compare1<int>());
  1. 如果没有显式地传入compare函数,则默认使用迭代器指示的元素的operator<函数
// 如果容器中的元素是下面这个struct element类型,则实现该类型的operator<函数。
// 从上面stl源码可以得知,如果没有传入compare函数,则默认调用元素的operator<。
struct element
{
    bool operator<(const element& rhs)
    {
        return a < rhs.a;
    }

    int a;
};

sort适用场景

在SGI STL中根据读写和访问方式,在源码中迭代器大致可分为五类:

输入迭代器input_iterator: 只读,且只能一次读操作,支持操作:++p,p++,!=,==,=*p,p->;
输出迭代器output_iterator: 只写,且只能一次写操作,支持操作:++p,p++;
正向迭代器forward_iterator: 可多次读写,支持输入输出迭代器的所有操作;
双向迭代器bidirectional_iterator: 支持正向迭代器的所有操作,且支持操作:--p,--p;
随机访问迭代器random_access_iterator: 除了支持双向迭代器操作外,还支持:p[n],p+n,
n+p,p-n,p+=n,p-=n,p1-p2,p1<p2,p1>p2,p1>=p2,p1<=p2;

从sort源码定义可知,sort支持的类型应该是RandomAccessIterator,也即随机访问迭代器。
map,set,list显然都不支持RandomAccessIterator,而是bidirectional_iterator。所以sort不能直接用于对map,set的排序。
list有自己的成员sort方法。
queue本身的特性,queue没有迭代器。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值