网站优化哪家好鹤山市城乡住房建设部网站
news/
2025/9/30 6:22:10/
文章来源:
网站优化哪家好,鹤山市城乡住房建设部网站,纯文本网站连接,泰安网站建设哪里找heap不属于STL容器的组件#xff0c;属于幕后角色#xff0c;是priority_queue的助手priority_queue 允许用户以任何次序将任何元素推入容器内#xff0c;但是取出的时候需要从优先级最高(也就是数值最高)的元素开始取#xff0c;这种思想是基于heap的函数实现如果使用list…heap不属于STL容器的组件属于幕后角色是priority_queue的助手priority_queue 允许用户以任何次序将任何元素推入容器内但是取出的时候需要从优先级最高(也就是数值最高)的元素开始取这种思想是基于heap的函数实现如果使用list作为 priority_queue 的底层实现机制元素的插入操作可以使用常数的时间但是不好找 极值需要进行线性扫描和遍历如果考虑到大小这个关键因素进行元素的排序随后进行元素之间的衔接降低了元素的插入效率使用binary search tree作为priority的底层机制这样对于元素的插入和取极值就有O(logN)的表现但是缺点是1binary search tree需要具备足够的随机性2binary search tree实现很难binary heap是一种 complate binary tree(完全二叉树)除了最底层叶节点之外都是处于饱和的状态而最底层的叶节点从左只有不得有空隙示例如下complate binary tree(完全二叉树)整棵树内部没有任何的节点漏洞好处1使用array存储所有的节点保留#0 元素的位置 (将其设为无限大或者无限小),那么当 complate binary tree(完全二叉树)的某个节点位于array数组中的i处的时候其左子树节点必然位于array的 2i 处其右子树的节点必然位于array的 2*i1 的位置。 ( 这里的 / 表示取整数)通过保留#0 的操作可以使用array轻而易举实现出complate binary tree。使用数组的方式表达完全二叉树的方式 称为隐式 表述法考虑到array无法动态的改变大小使用vector代替array实现 完全二叉树根据元素的排列方式 heap分为max-heap和min-heap前者每个节点的键值 都大于或者等于其子节点的键值 后者 每个节点的键值都小于或者等于其每个子节点的键值max-heap 最大值在根节点其总是位于底层的array或者vector的开头min-heap 最小值在根节点其总是位于底层的array或者vector的开头STL 供应的是 max-heap 本文所有的heap都按照 max-heap处理
heap的算法
push_heap 算法
新加入的元素一定是放在最下一层作为叶节点并填补从左到右的第一个空格也就是底层vector()的end()处执行上溯程序将新节点和父接地那记性比较如果大于父节点就进行父子对换如此一直上溯直到不需要对换或者直到遇到根节点为止接收两个迭代器表示heap的底部操作(vector)的头尾并且新的元素插入到底部容器的最尾端如果不符合这两个条件那么push_heap的结果是不可预期的distance_type 方便的决定某个迭代器的类型 参考链接如下STL源码剖析 5中迭代器型别_CHYabc123456hh的博客-CSDN博客
templateclass RandomAccessIterator
inline void push_heap(RandomAccessIterator first,RandomAccessIterator last){//函数被调用的时候 新元素应已经置于底部容器的最尾端//distance_type 用于判断迭代器的类型从而判定是否进行偏特化操作__push_heap_aux(first,last,distance_type(first),value_type(first));
}template class RandomAccessIterator,class Distance,class T
inline void __push_heap_aux(RandomAccessIterator first,RandomAccessIterator last,Distance *,T*){//根据implicit representation heap的结构特性新值必须置于底部容器的最尾端即第一个洞号(last-first)-1__push_heap(first,Distance((last-first)-1),Distance(0),T(*(last-1)));
}//以下这组push_back() 不允许指定 大小比较的标准
template class RandomAccessIterator,class Distance, class T
void __push_heap(RandomAccessIterator first,Distance holeIndex,Distance topIndex,T value){Distance parent (holeIndex - 1)/2; //找出父节点//当holeIndex并没有到达顶峰的同时 父节点还小于新值 不符合heap的次序特性//使用operator 进行元素的比较因此STL heap是一种max-heap//父节点是动态变化的//每次是和value进行比较因此不需要进行父子元素值的对调直接让子元素接管父亲的数值while(holeIndex topIndex *(first parent) value){*(first holeIndex) *(first parent); //令洞值为父值,也就是孩子赋予了父亲的数值父亲位置holeIndex parent; //调整洞号向上提升至父节点parent (holeIndex - 1)/2;//新洞的父节点}//持续至顶端或者满足 heap的次序特性为止*(first holeIndex) value;//令新洞为新的数值完成插入操作
}pop_heap() 算法
弹出最大元素根节点缺失需要使用最末尾的元素进行弥补然后执行下放程序将根节点的数值和最大的叶子节点进行互换以此类推直到这个洞的键值大于左右两个子节点或者下放至叶子节点为止pop_heap代码
//这个堆没有指定 大小比较的标准
template class RandomAccessIterator,class T,class Distance
inline void __pop_heap(RandomAccessIterator first,RandomAccessIterator last,RandomAccessIterator result,T value,Distance *){*result *first; //设定尾值为首值也就是此刻的尾值为先前的根节点//可以通过底层容器的 pop_back()取出尾值//重新调整 heap 洞号为0(即树根处)将其数值设定为 value(先前的尾节点的数值)__adjust_heap(first,Distance(0),Distance(last-first),value);
}//这个堆没有指定 大小比较的标准
template class RandomAccessIterator,class Distance,class T
void __adjust_heap(RandomAccessIterator first,Distance holeIndex,Distance len,T value){Distance topIndex holeIndex;Distance secondChild 2 * holeIndex 2;//洞节点的右子节点while(secondChild len){//比较洞节点的左右两个孩子的数值然后以secondChild代表较大的子节点if (*(first secondChild) *(first secondChild -1)){secondChild--;}//令较大的子值为洞值 再令洞号下降至较大的子节点处*(first holeIndex) *(first secondChild);holeIndex secondChild;//找出新洞节点的右子节点secondChild 2 * (secondChild 1);}if (secondChild len){//没有右边节点 只有左边的节点//将左子值设为洞值 再令洞号下移至 左子节点处*(firstholeIndex) *(first secondChild - 1);holeIndex secondChild - 1;}*(first holeIndex) value;
}pop_heap之后最大元素将被放置于底部容器的最尾端并没有被取走。可以使用底部容器提供的back()函数获取这个数值也可以使用vector提供的pop_back()函数将其移除
sort_heap()
pop_heap可以获得heap中键值最大的元素持续使用pop_heap,不断得到最大的元素就可以实现排序。需要注意的是每没用一次pop_heap都需要将操作范围从后向前缩减一个元素。sort_heap()函数接收两个迭代器用来表现一个heap底部容器的头尾。如果不符合这个条件sort_heap的排序结果未可预期。*排序过后的heap已经被破坏不再是一个合法的堆了相当于操作底层的元素修改了元素破坏性是无法修改的
template class RandomAccessIterator
void sort_heap(RandomAccessIterator first,RandomAccessIterator last){//每执行一次pop_heap(),极值(在STL heap中为极大值)就会被放在尾端//扣除尾端再次执行pop_heap()次极值又被放在新的尾端按照上述流程一直执行最后得到排序结果while (last - first 1){std::pop_heap(first,last--);//每次执行pop_heap()一次操作范围即缩减一格}
} make_heap() 这个函数的目的是为了将一段现有的数据将其转化为堆的形式主要依据就是complate binary tree 的隐式表述
template class RandomAccessIterator,class T,class Distance
void __make_heap(RandomAccessIterator first,RandomAccessIterator last,T*,Distance *){if (last - first 2){ //如果长度为0或者为1不需要重新排列return;}Distance len last - first;//找出第一个需要重新排列的子树的头部以parent标定//考虑到任何节点不需要执行perlocate down因此使用hole Index进行命名更好Distance parent (len - 2)/2;while (true){//重新排列以parent为首的子树//len的目的是为了让__adjust_heap() 判断操作的范围__adjust_heap(first,parent,len,T(*(first parent)));if (parent 0){return; //走完根节点 结束}parent--; // (即将重拍子树的)头部向前一个节点}
}
heap没有迭代器 heap不提供遍历的功能也不提供迭代器
测试用例
int main(){int ia[9] {0,1,2,3,4,8,9,3,5};std::vectorint i_vec(ia,ia9);std::make_heap(i_vec.begin(),i_vec.end());for (int i 0; i i_vec.size(); i) {std::cout i_vec[i] ; //9 5 8 3 4 0 2 3 1}std::cout std::endl;i_vec.push_back(7);std::push_heap(i_vec.begin(),i_vec.end());for (int i 0; i i_vec.size(); i) {std::cout i_vec[i] ; //9 7 8 3 5 0 2 3 1 4}std::cout std::endl;std::pop_heap(i_vec.begin(),i_vec.end());std::cout i_vec.back() std::endl; //9 return but no removei_vec.pop_back(); //remove last elem and no returnfor (int i 0; i i_vec.size(); i) {std::cout i_vec[i] ; //8 7 4 3 5 0 2 3 1}std::cout std::endl;std::sort_heap(i_vec.begin(),i_vec.end());for (int i 0; i i_vec.size(); i) {std::cout i_vec[i] ; //0 1 2 3 3 4 5 7 8}std::cout std::endl;{//test heap (底层使用array实现)int ia[9] {0,1,2,3,4,8,9,3,5};std::make_heap(ia,ia9);//array不能动态的改变大小因此不可以对满载的array进行push_heap()操作//需要先在array的尾端增加一个元素std::sort_heap(ia,ia9);for (int i 0; i 9; i) {std::cout ia[i] ; //0 1 2 3 3 4 5 8 9}std::cout std::endl;//经过排序之后的heap 不再是一个合法的heap//重新再做一个heapstd::make_heap(ia,ia9);std::pop_heap(ia,ia9);std::cout ia[8] std::endl; //8}
}
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/922531.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!