一组合算法。

本文介绍了一种基于组合思想的排序方法及相关的组合算法实现,包括初始化组合、获取下一个组合等,并提供了详细的模板函数实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

namespace btb
{
  ////////////////////////////////////////////////////////////////////
  // combination for STL permutation
  //
  // init_combination    (first, middle, last)
  // adjust_combination  (first, middle, last)
  // combination         (first1, last1, first2, last2)
  // next_combination    (first, middle, last)
  // prev_combination    (first, middle, last)
  ////////////////////////////////////////////////////////////////////

  ////////////////////////////////////////////////////////////////////
  // separate_merge: merge [first1, last1) and [first2, last2), then fill
  //              the min element to [first1, last1), left to [first2,
  //              last2)
  ////////////////////////////////////////////////////////////////////
  template <typename Iter>
  void
  separate_merge (Iter first1, Iter last1, Iter first2, Iter last2)
  {
    typedef typename std::iterator_traits<Iter>::value_type value_type;
    typedef typename std::iterator_traits<Iter>::difference_type diff_t;

    if ((first1 == last1) || (first2 == last2))
      return;
    first1 = std::upper_bound(first1, last1, *first2);
    if (first1 == last1)
      return;
    last2 = std::lower_bound(first2, last2, *(last1-1));
    if (first2 == last2)
      return;

    diff_t len1 = std::distance(first1, last1);
    diff_t len2 = std::distance(first2, last2);
    bool min1 = len1 < len2;
    diff_t lent = min1 ? len1 : len2;
    value_type *tmp = new value_type[lent];

    if (min1)
      {
std::copy(first1, last1, tmp);
Iter p = first2;
value_type* q = tmp;
Iter i;
for (i = first1; i != last1; ++i)
  if (*p < *q)
    *i = *p++;
  else
    *i = *q++;
for (i = first2; (i != last2) && (p != last2); ++i)
  if (*p < *q)
    *i = *p++;
  else
    *i = *q++;
for (; i != last2; ++i, ++q)
  *i = *q;
      }
    else
      {
std::copy(first2, last2, tmp);
Iter p = last1;
value_type* q = tmp+lent;
Iter i;
for (Iter i = last2; i != first2;)
  if (*(p-1) < *(q-1))
    *--i = *--q;
  else
    *--i = *--p;
for (i = last1; (i != first1) && (p != first1);)
  if (*(p-1) < *(q-1))
    *--i = *--q;
  else
    *--i = *--p;
for (; i != first1;)
  *--i = *--q;
      }

    delete[] tmp;
  }

  ///////////////////////////////////////////////////////////////////
  // __combination_sort: merge sort the [first, last)
  ///////////////////////////////////////////////////////////////////
  template <typename Iter>
  void
  __combination_sort (Iter first, Iter last)
  {
    typedef typename std::iterator_traits<Iter>::difference_type diff_t;
    diff_t len = std::distance(first, last);
    if (len <= 1)
      return;

    if (len == 2)
      {
if (*first > *--last)
  std::iter_swap (first, last);
      }
    else
      {
Iter middle = first;
std::advance(middle, len / 2);
__combination_sort (first, middle);
__combination_sort (middle, last);
separate_merge (first, middle, middle, last);
      }
  }

  //////////////////////////////////////////////////////////////////////
  // init_combination: init the (first, midle, last) to the min or the
  //                   max combination
  //////////////////////////////////////////////////////////////////////
  template <typename Iter>
  void
  init_combination (Iter first, Iter middle, Iter last, bool min = true)
  {
    __combination_sort (first, middle);
    __combination_sort (middle, last);
    if (min)
      separate_merge (first, middle, middle, last);
    else
      separate_merge (middle, last, first, middle);
  }

  //////////////////////////////////////////////////////////////////////
  // adjust_combination: make the (first, middle, last) to a right
  //                     combination. [first, middle) are the elements
  //                     selected in, [middle, last) are selected out
  //////////////////////////////////////////////////////////////////////
  template <typename Iter>
  void
  adjust_combination (Iter first, Iter middle, Iter last)
  {
    __combination_sort (first, middle);
    __combination_sort (middle, last);
  }

  /////////////////////////////////////////////////////////////////////
  // combination: get next combination.
  //
  // [first1, last1): the elements selected in //
  // [first2, last2): the elements selected out
  /////////////////////////////////////////////////////////////////////
  template <typename Iter>
  bool
  combination (Iter first1, Iter last1, Iter first2, Iter last2)
  {
    if ((first1 == last1) || (first2 == last2))
      return false;

    Iter qmax = last2;
    --qmax;
    Iter pout1 = std::lower_bound(first1, last1, *qmax);
    bool fin = pout1 == first1;
    Iter left1, left2;
    if (!fin)
      {
Iter pout = pout1;
--pout;
Iter qin = std::upper_bound(first2, last2, *pout);
std::iter_swap (pout, qin);
left1 = pout;
++left1;
left2 = qin;
++left2;
      }
    else
      {
left1 = first1;
left2 = first2;
      }
    separate_merge (left1, last1, left2, last2);
    return !fin;
  }

  /////////////////////////////////////////////////////////////////////
  // next_combination: get next combination.
  //
  // [first, middle): the elements selected in //
  // [middle, last): the elements selected out
  /////////////////////////////////////////////////////////////////////
  template <typename Iter>
  inline bool
  next_combination (Iter first, Iter middle, Iter last)
  {
    return combination (first, middle, middle, last);
  }

  /////////////////////////////////////////////////////////////////////
  // prev_combination: get prev combination.
  //
  // [first, middle): the elements selected in //
  // [middle, last): the elements selected out
  /////////////////////////////////////////////////////////////////////
  template <typename Iter>
  inline bool
  prev_combination (Iter first, Iter middle, Iter last)
  {
    return combination (middle, last, first, middle);
  }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值