显示标签为“STL”的博文。显示所有博文
显示标签为“STL”的博文。显示所有博文

2012年5月17日星期四

std::map的小小失误



std::map的小小失误


# 故事简介

完全属于我的脑子失误,短暂的弱智时刻,导致该失误的诞生,’罪过‘。
由于项目开发,需增加一逻辑:过滤同样的某接口调用的请求,保持内部响应逻辑处理系统不允许存在一个以上同样的请求。
请求内容包括ID和参数,两者可以区分出不同调用请求。
Request = { RequestID,RequestParam } 

# 失误情况

使用 std::multimap 结构做记录。添加、删除、测试(验证)记录条目。
详细定义,如下:

namespace query_lib
{
typedef std::multimap<int, std::pair<std::string, size_t> > request_record_type;
static request_record_type     _request_record;


/// 记录或标记函数功能请求 标记类型 pair<func_id, pair<func_param, record> >
bool add_request_record(const request_record_type::value_type& obj)
{
    /// Lock lock(...);// todo lock
    request_record_type::iterator lower_it = _request_record.upper_bound(obj.first);
    for (; lower_it != _request_record.end(); ++lower_it )
    {
        if (lower_it->first != obj.first)
            break;
        else if ( lower_it->second.first == obj.second.first)
        {
            ++lower_it->second.second;
            return false;
        }
    }
    _request_record.insert(lower_it, obj);
    return true;
}
/// 擦除函数功能请求的记录或标记 标记类型 pair<func_id, pair<func_param, record> >
void del_request_record(const request_record_type::value_type& obj)
{
    /// Lock lock(...);// todo lock
    request_record_type::iterator upper_it = _request_record.upper_bound(obj.first);
    request_record_type::iterator lower_it = _request_record.lower_bound(obj.first);

    for (request_record_type::iterator iter = upper_it; iter != lower_it; ++iter)
    {
        if (iter->first == obj.first && iter->second.first == obj.second.first)
        {
            if (0 != iter->second.second)
            {
                --(iter->second.second);
            }
            else
                assert(false);
        }

    }
}
bool test_request_record(const request_record_type::value_type& obj)
{
    /// Lock lock(...);// todo lock
    request_record_type::iterator upper_it = _request_record.upper_bound(obj.first);
    request_record_type::iterator lower_it = upper_it;
    for (; lower_it != _request_record.end();
        ++lower_it )
    {
        if (lower_it->first != obj.first)
            break;
        else if ( lower_it->second.first == obj.second.first &&
            obj.second.second != 0)
            return true;
    }
    return false;
}

# 问题解析
诶,简单一句话。颠倒了map::lower_bound & map::upper_bound两成员函数的含义。
罪过啊,浪费了设计,测试,调错,修改过程的数小时(3H+)时间啊,而且那时加班时间!
转,Look following ……
---
public member function

map::lower_bound

      iterator lower_bound ( const key_type& x );
const_iterator lower_bound ( const key_type& x ) const;
Return iterator to lower bound
Returns an iterator pointing to the first element in the container whose key does not compare less than x (using the container's comparison object), i.e. it is either equal or greater.

Unlike upper_bound, this member function returns an iterator to the element also if it compares equal to x and not only if it compares greater.


Notice that, internally, all the elements in a map container are always ordered by their keys following the criterion defined by its comparison object, therefore all the elements that follow the one returned by this function will have a key that compares greater than x.
---

举个明显的例子说明吧,如下:
map = { (1,a), (2, b), (2, c), (2, d), (3, e), (4, f) }

map.lower_bound(2) => (2, b)
map.lupper_bound(2) => (3, e)

# 忠告建议

     当你在想好了设计要开始编写算法逻辑的代码时,再次提醒“清晰确认使用的基本元素”!

# 链接

修改后,正确的程序参见链接页面

2012年1月12日星期四

STL稳定排序源码分析

STL稳定排序源码分析
 -- std::stable_sort源码学习笔记




发表于 2011年11月07日 10:41

# 背景说明
先贴一张图吧:



前几天,一个新同事前来询问算法stl-stable_sort的情况。由于离上次研读stl源码时间久已(两三年前的事儿了),有些细节笔记模糊了。所以就找了sgi-stl和ms-stl俩版本,重新复习一遍其中的stl-stable_sort算法。稍微简单整理了阅读笔记,主要裁剪sgi-stl源码的“伪代码”,顺便加些注释还可看懂一二!sgi-stl 可读性笔记强。
    事后,和新同事们讲解,分享该算法的内在,主要想说明区别于通用型的std::sort。 
    希望贴出来,对于一些新学者有点用处! 

===
源码分析

Title: [ std::stable_sort源码学习笔记 ]

===== begin =====
 STL算法 (稳定)在位排序
 stable_sort(__first,  __last) {
 // 关键点1:申请排序缓冲区
  _Temporary_buffer<_RandomAccessIter, _Tp> buf(__first, __last);
  if (buf.begin() == 0)
    __inplace_stable_sort(__first, __last);//若缓冲区为空则内部排序。
  else 
    __stable_sort_adaptive(__first, __last, buf.begin(),
                           _Distance(buf.size()));//转调 
}
=====>>>>>
转调的在位排序,实则归并排序。
__stable_sort_adaptive(__first, __last, __buffer,__buffer_size) {
// 关键点2:递归,归并排序!
  __len = (__last - __first + 1) / 2;
  __middle = __first + __len;
  if (__len > __buffer_size) {
    __stable_sort_adaptive(__first, __middle, __buffer, __buffer_size);
    __stable_sort_adaptive(__middle, __last, __buffer, __buffer_size);
  }
  else {
    __merge_sort_with_buffer(__first, __middle, __buffer, (_Distance*)0);
    __merge_sort_with_buffer(__middle, __last, __buffer, (_Distance*)0);
  }
  __merge_adaptive(__first, __middle, __last, _Distance(__middle - __first), 
                   _Distance(__last - __middle), __buffer, __buffer_size);
}
=====>>>>>
借助缓冲区进行归并排序
__merge_sort_with_buffer(__first, __last, __buffer) {
  __len = __last - __first;
  __buffer_last = __buffer + __len;
  __step_size = __stl_chunk_size;// sgi stl 7
  // 关键点3:在整个集合分片地进行插入排序,保证每分片均有序。
  __chunk_insertion_sort(__first, __last, __step_size);
  // 关键点4:合并不同分片(有序的)元素。
  while (__step_size < __len) {
    __merge_sort_loop(__first, __last, __buffer, __step_size);
    __step_size *= 2;
    __merge_sort_loop(__buffer, __buffer_last, __first, __step_size);
    __step_size *= 2;
  }
}
=====>>>>> 
__merge_sort_loop(__first,  __last, __result, __step_size) {
  __two_step = 2 * __step_size;
  while (__last - __first >= __two_step) {
    __result = merge(__first, __first + __step_size,
                     __first + __step_size, __first + __two_step,
                     __result);
    __first += __two_step;
  }

  __step_size = min((__last - __first), __step_size);
  merge(__first, __first + __step_size, __first + __step_size, __last,
        __result);
}
=====>>>>>
将集合切分若干分片,排序每分片元素。
__chunk_insertion_sort(__first, __last, __chunk_size)
{
  while (__last - __first >= __chunk_size) {
    __insertion_sort(__first, __first + __chunk_size);
    __first += __chunk_size;
  }
  __insertion_sort(__first, __last);
}
=====>>>>>
插入排序
__insertion_sort(__first, __last) { 
  for (__i = __first + 1; __i != __last; ++__i)
    __linear_insert(__first, __i, __VALUE_TYPE(__first));
}
=====>>>>>
__linear_insert( __first, __last, _Tp*) {
  if (__val < *__first) {
    copy_backward(__first, __last, __last + 1);
    *__first = __val;
  }
  else
    __unguarded_linear_insert(__last, __val);
}
=====>>>>>
__unguarded_linear_insert(__last, __val) {
  __next = __last;
  --__next;
  while (__val < *__next) {
    *__last = *__next;
    __last = __next;
    --__next;
  }
  *__last = __val;
}
===== end =====

@huangjunkun/2011-11-01/

# 附说明


在线流程图简洁工具:http://www.websequencediagrams.com/
code:

stable_sort -> __stable_sort_adaptive :申请排序缓冲区
__stable_sort_adaptive -> __merge_sort_with_buffer:借助缓冲区,\n递归地归并排序!
__merge_sort_with_buffer -> __merge_sort_loop:集合切分分片,\n插入排序各分片,\n保证分片均有序;\n合并不同有序分片。
__merge_sort_loop  -> merge :以分治法切分\n进行合并排序
merge -> __chunk_insertion_sort :将集合切分若干分片,\n排序每分片元素。
__chunk_insertion_sort -> __insertion_sort:插入排序
__insertion_sort -> __linear_insert: 
__linear_insert -> __unguarded_linear_insert: 
__unguarded_linear_insert -> end: