一、heap

heap并不属于STL容器组件,它分为 max heap 和min heap,在缺省情况下,max-heap是优先队列(priority queue)的底层实现机制。而这个实现机制中的max-heap实际上
是以一个vector表现的完全二叉树(complete binary tree)。STL在<algorithm.h>中实现了对 存储在vector/deque 中的元素进行堆操作的函数,包括make_heap, pop_heap, push_heap, sort_heap,对不愿自己写数据结构堆的C++选手来说,这几个算法函数很有用,详细解释可以参见: http://www.cplusplus.com/reference/algorithm/make_heap/

下面的_First与_Last为可以随机访问的迭代器(指针),_Comp为比较函数(仿函数),其规则——如果函数的第一个参数小于第二个参数应返回true,否则返回false。

1.make_heap():

make_heap(_First, _Last)

make_heap(_First, _Last, _Comp)

默认是建立最大堆的。对int类型,可以在第三个参数传入greater<int>()得到最小堆。

2.push_heap(_First, _Last):

新添加一个元素在末尾,然后重新调整堆序。也就是把元素添加在底层vector的end()处。

该算法必须是在一个已经满足堆序的条件下,添加元素。该函数接受两个随机迭代器,分别表示first,end,区间范围。

关键是我们执行一个siftup()函数,上溯函数来重新调整堆序。具体的函数机理很简单,可以参考我的编程珠玑里面堆的实现的文章。

3.pop_heap(_First, _Last):

这个算法跟push_heap类似,参数一样。不同的是我们把堆顶元素取出来,放到了数组或者是vector的末尾,用原来末尾元素去替代,然后end迭代器减1,执行siftdown()下溯函数来重新调整堆序。

注意算法执行完毕后,最大的元素并没有被取走,而是放于底层容器的末尾。如果要取走,则可以使用底部容器(vector)提供的pop_back()函数。

4.sort_heap(_First, _Last):

既然每次pop_heap可以获得堆中最大的元素,那么我们持续对整个heap做pop_heap操作,每次将操作的范围向前缩减一个元素。当整个程序执行完毕后,我们得到一个非降的序列。注意这个排序执行的前提是,在一个堆上执行。

下面是这几个函数操作vector中元素的例子。

  1. #include<iostream>
  2. #include<vector>
  3. #include<algorithm>
  4.  
  5. using namespace std;
  6.  
  7. int main()
  8. {
  9. int a[] = {15, 1, 12, 30, 20};
  10. vector<int> ivec(a, a+5);
  11. for(vector<int>::iterator iter=ivec.begin();iter!=ivec.end();++iter)
  12. cout<<*iter<<" ";
  13. cout<<endl;
  14.  
  15. make_heap(ivec.begin(), ivec.end());//建堆
  16. for(vector<int>::iterator iter=ivec.begin();iter!=ivec.end();++iter)
  17. cout<<*iter<<" ";
  18. cout<<endl;
  19.  
  20. pop_heap(ivec.begin(), ivec.end());//先pop,然后在容器中删除
  21. ivec.pop_back();
  22. for(vector<int>::iterator iter=ivec.begin();iter!=ivec.end();++iter)
  23. cout<<*iter<<" ";
  24. cout<<endl;
  25.  
  26. ivec.push_back(99);//先在容器中加入,再push
  27. push_heap(ivec.begin(), ivec.end());
  28. for(vector<int>::iterator iter=ivec.begin();iter!=ivec.end();++iter)
  29. cout<<*iter<<" ";
  30. cout<<endl;
  31.  
  32. sort_heap(ivec.begin(), ivec.end());
  33. for(vector<int>::iterator iter=ivec.begin();iter!=ivec.end();++iter)
  34. cout<<*iter<<" ";
  35. cout<<endl;
  36.  
  37. return 0;
  38. }

二、priority queue

优先队列(priority_queue)首先是一个queue,那就是必须在末端推入,必须在顶端取出元素。除此之外别无其他存取元素的途径。内部元素按优先级高低排序,优先级高的在前。缺省情况下,priority_heap利用一个max-heap完成,后者是一个以vector表现的完全二叉树。我们说优先队列不是一个STL容器,它以底部容器而实现,修改了接口,形成另一种性质,这样的东西称之为适配器(adapter)。

详情参见: http://www.cplusplus.com/reference/stl/priority_queue/

优先级队列是一个拥有权值观念的queue。它允许在底端添加元素、在顶端去除元素、删除元素。

优先级队列内部的元素并不是按照添加的顺序排列,而是自动依照元素的权值排列。权值最高者排在最前面。

缺省情况下,优先级队列利用一个大顶堆完成。关于堆可以参考:STL堆详解与编程实现

优先级队列以底部容器完成其所有工作,具有这种“修改某物接口,形成另一种风貌”这种性质者,成为配接器(adapter)。在STL中优先级队列不被归类为容器,而被归类为容器配接器(container
adapter)

priority_queue 对于基本类型的使用方法相对简单。

他的模板声明带有三个参数,priority_queue<Type, Container, Functional>

Type 为数据类型, Container 为保存数据的容器,Functional 为元素比较方式。

Container 必须是用数组实现的容器,比如 vector, deque 但不能用 list.

STL里面容器默认用的是 vector. 比较方式默认用 operator< , 所以如果你把后面俩个参数 缺省的话,优先队列就是大顶堆,队头元素最大。

看例子

  1. #include <iostream>
  2. #include <queue>
  3. using namespace std;
  4. int main(){
  5. priority_queue<int,vector<int>,less<int> >q;//使用priority_queue<int> q1;一样
  6. for(int i=0;i<10;i++)
  7. q1.push(i);
  8. while(!q1.empty()){
  9. cout<<q1.top()<< endl;
  10. q1.pop();
  11. }
  12. return 0;
  13. }

如果要用到小顶堆,则一般要把模板的三个参数都带进去。

STL里面定义了一个仿函数 greater<>,对于基本类型可以用这个仿函数声明小顶堆

例子:

  1. #include <iostream>
  2. #include <queue>
  3. using namespace std;
  4. int main(){
  5. priority_queue<int,vector<int>,greater<int> >q;
  6. for(int i=0;i<10;i++)
  7. q.push(i);
  8. while(!q.empty()){
  9. cout<<q.top()<< endl;
  10. q.pop();
  11. }
  12. return 0;
  13. }

对于自定义类型,则必须自己重载 operator< 或者自己写仿函数先看看例子:

  1. #include <iostream>
  2. #include <queue>
  3. using namespace std;
  4. struct Node{
  5. int x, y;
  6. }node;
  7. bool operator<( Node a, Node b){
  8. if(a.x==b.x) return a.y>b.y;
  9. return a.x>b.x;
  10. }
  11. int main(){
  12. priority_queue<Node>q;
  13. for(int i=0;i<10;i++){
  14. node.x=i;
  15. node.y=10-i/2;
  16. q.push(node);
  17. }
  18. while(!q.empty()){
  19. cout<<q.top().x <<' '<<q.top().y<<endl;
  20. q.pop();
  21. }
  22. return 0;
  23. }

自定义类型重载 operator< 后,声明对象时就可以只带一个模板参数。

此时不能像基本类型这样声明priority_queue<Node, vector<Node>, greater<Node> >;

原因是 greater<Node> 没有定义,如果想用这种方法定义

则可以按如下方式例子:(个人喜欢这种方法,因为set的自定义比较函数也可以写成这种形式)

  1. #include <iostream>
  2. #include <queue>
  3. using namespace std;
  4. struct Node{
  5. int x, y;
  6. }node;
  7. struct cmp{
  8. bool operator()(Node a,Node b){
  9. if(a.x==b.x) return a.y>b.y;
  10. return a.x>b.x;}
  11. };
  12.  
  13. int main(){
  14. priority_queue<Node,vector<Node>,cmp>q;
  15. for(int i=0;i<10;i++){
  16. node.x=i;
  17. node.y=10-i/2;
  18. q.push(node);
  19. }
  20. while(!q.empty()){
  21. cout<<q.top().x<<' '<<q.top().y<<endl;
  22. q.pop();
  23. }
  24. return 0;
  25. }

SGI STL中优先级队列定义

定义完整代码:

  1. template <class T, class Sequence = vector<T>,
  2. class Compare = less<typename Sequence::value_type> >
  3. class priority_queue {
  4. public:
  5. typedef typename Sequence::value_type value_type;
  6. typedef typename Sequence::size_type size_type;
  7. typedef typename Sequence::reference reference;
  8. typedef typename Sequence::const_referenceconst_reference;
  9. protected:
  10. Sequence c; //底层容器
  11. Compare comp;//元素大小比较标准
  12. public:
  13. priority_queue() : c() {}
  14. explicit priority_queue(const Compare& x) : c(), comp(x) {}
  15.  
  16. //以下用到的 make_heap(), push_heap(), pop_heap()都是泛型算法
  17. //注意,任一个建构式都立刻于底层容器内产生一个 implicit representation heap。
  18. template <class InputIterator>
  19. priority_queue(InputIterator first, InputIterator last, const Compare& x)
  20. : c(first, last), comp(x) {make_heap(c.begin(), c.end(), comp); }
  21. template <class InputIterator>
  22. priority_queue(InputIterator first, InputIterator last)
  23. : c(first, last) { make_heap(c.begin(), c.end(), comp); }
  24.  
  25. bool empty() const { return c.empty(); }
  26. size_typesize() const { return c.size(); }
  27. const_referencetop() const { return c.front(); }
  28. void push(const value_type& x) {
  29. __STL_TRY {
  30. // push_heap是泛型算法,先利用底层容器的 push_back() 将新元素
  31. // 推入᳿端,再重排 heap。见 C++ Primer p.1195。
  32. c.push_back(x);
  33. push_heap(c.begin(), c.end(), comp);// push_heap是泛型算法
  34. }
  35. __STL_UNWIND(c.clear());
  36. }
  37. void pop() {
  38. __STL_TRY {
  39. // pop_heap 是泛型算法,从 heap 内取出一个元素。它并不是真正将元素
  40. // 弹出,而是重排 heap,然后再以底层容器的 pop_back() 取得被弹出
  41. // 的元素。见 C++ Primer p.1195。
  42. pop_heap(c.begin(), c.end(), comp);
  43. c.pop_back();
  44. }
  45. __STL_UNWIND(c.clear());
  46. }
  47. };

优先级队列编程实现(C Plus Plus)

在这里自己用C++编程实现了简易版的优先级队列。

其中用到了前一篇博客里面的堆heap.h:

  1. //STL堆算法实现(大顶堆)
  2.  
  3. //包含容器vector的头文件:Heap用vector来存储元素
  4. #include <vector>
  5. #include <iostream>
  6. #include <functional>
  7.  
  8. #define MAX_VALUE 999999 //某个很大的值,存放在vector的第一个位置(最大堆)
  9.  
  10. const int StartIndex = 1;//容器中堆元素起始索引
  11.  
  12. using namespace std;
  13.  
  14. //堆类定义
  15. //默认比较规则less
  16. template <class ElemType,class Compare = less<ElemType> >
  17. class MyHeap{
  18. private:
  19. vector<ElemType> heapDataVec;//存放元素的容器
  20. int numCounts;//堆中元素个数
  21. Compare comp;//比较规则
  22.  
  23. public:
  24. MyHeap();
  25.  
  26. vector<ElemType>& getVec();
  27.  
  28. void initHeap(ElemType *data,const int n);//初始化操作
  29. void printfHeap();//输出堆元素
  30. void makeHeap();//建堆
  31. void sortHeap();//堆排序算法
  32. void pushHeap(ElemType elem);//向堆中插入元素
  33. void popHeap();//从堆中取出堆顶的元素
  34. void adjustHeap(int childTree,ElemType adjustValue);//调整子树
  35. void percolateUp(int holeIndex,ElemType adjustValue);//上溯操作
  36.  
  37. void setNumCounts(int val);//设置当前所要构建的堆中元素个数
  38. };
  39.  
  40. template <class ElemType,class Compare>
  41. MyHeap<ElemType,Compare>::MyHeap()
  42. :numCounts(0)
  43. {
  44. heapDataVec.push_back(MAX_VALUE);
  45. }
  46.  
  47. template <class ElemType,class Compare>
  48. vector<ElemType>& MyHeap<ElemType,Compare>::getVec()
  49. {
  50. return heapDataVec;
  51. }
  52.  
  53. template <class ElemType,class Compare>
  54. void MyHeap<ElemType,Compare>::initHeap(ElemType *data,const int n)
  55. {
  56. //拷贝元素数据到vector中
  57. for (int i = 0;i < n;++i)
  58. {
  59. heapDataVec.push_back(*(data + i));
  60. ++numCounts;
  61. }
  62. }
  63.  
  64. template <class ElemType,class Compare>
  65. void MyHeap<ElemType,Compare>::printfHeap()
  66. {
  67. cout << "Heap : ";
  68. for (int i = 1;i <= numCounts;++i)
  69. {
  70. cout << heapDataVec[i] << " ";
  71. }
  72. cout << endl;
  73. }
  74.  
  75. template <class ElemType,class Compare>
  76. void MyHeap<ElemType,Compare>::makeHeap()
  77. {
  78. //建堆的过程就是一个不断调整堆的过程,循环调用函数adjustHeap依次调整子树
  79. if (numCounts < 2)
  80. return;
  81. //第一个需要调整的子树的根节点多音
  82. int parent = numCounts / 2;
  83. while(1)
  84. {
  85. adjustHeap(parent,heapDataVec[parent]);
  86. if (StartIndex == parent)//到达根节点
  87. return;
  88.  
  89. --parent;
  90. }
  91. }
  92.  
  93. template <class ElemType,class Compare>
  94. void MyHeap<ElemType,Compare>::sortHeap()
  95. {
  96. //堆排序思路
  97. //每执行一次popHeap操作,堆顶的元素被放置在尾端,然后针对前面的一次再执行popHeap操作
  98. //依次下去,最后即得到排序结果
  99. while(numCounts > 0)
  100. popHeap();
  101. }
  102.  
  103. template <class ElemType,class Compare>
  104. void MyHeap<ElemType,Compare>::pushHeap(ElemType elem)
  105. {
  106. //将新元素添加到vector中
  107. heapDataVec.push_back(elem);
  108. ++numCounts;
  109.  
  110. //执行一次上溯操作,调整堆,以使其满足最大堆的性质
  111. percolateUp(numCounts,heapDataVec[numCounts]);
  112. }
  113.  
  114. template <class ElemType,class Compare>
  115. void MyHeap<ElemType,Compare>::popHeap()
  116. {
  117. //将堆顶的元素放在容器的最尾部,然后将尾部的原元素作为调整值,重新生成堆
  118. ElemType adjustValue = heapDataVec[numCounts];
  119. //堆顶元素为容器的首元素
  120. heapDataVec[numCounts] = heapDataVec[StartIndex];
  121. //堆中元素数目减一
  122. --numCounts;
  123.  
  124. adjustHeap(StartIndex,adjustValue);
  125. }
  126.  
  127. //调整以childTree为根的子树为堆
  128. template <class ElemType,class Compare>
  129. void MyHeap<ElemType,Compare>::adjustHeap(int childTree,ElemType adjustValue)
  130. {
  131. //洞节点索引
  132. int holeIndex = childTree;
  133. int secondChid = 2 * holeIndex + 1;//洞节点的右子节点(注意:起始索引从1开始)
  134. while(secondChid <= numCounts)
  135. {
  136. if (comp(heapDataVec[secondChid],heapDataVec[secondChid - 1]))
  137. {
  138. --secondChid;//表示两个子节点中值较大的那个
  139. }
  140.  
  141. //上溯
  142. heapDataVec[holeIndex] = heapDataVec[secondChid];//令较大值为洞值
  143. holeIndex = secondChid;//洞节点索引下移
  144. secondChid = 2 * secondChid + 1;//重新计算洞节点右子节点
  145. }
  146. //如果洞节点只有左子节点
  147. if (secondChid == numCounts + 1)
  148. {
  149. //令左子节点值为洞值
  150. heapDataVec[holeIndex] = heapDataVec[secondChid - 1];
  151. holeIndex = secondChid - 1;
  152. }
  153. //将调整值赋予洞节点
  154. heapDataVec[holeIndex] = adjustValue;
  155.  
  156. //此时可能尚未满足堆的特性,需要再执行一次上溯操作
  157. percolateUp(holeIndex,adjustValue);
  158. }
  159.  
  160. //上溯操作
  161. template <class ElemType,class Compare>
  162. void MyHeap<ElemType,Compare>::percolateUp(int holeIndex,ElemType adjustValue)
  163. {
  164. //将新节点与其父节点进行比较,如果键值比其父节点大,就父子交换位置。
  165. //如此,知道不需要对换或直到根节点为止
  166. int parentIndex = holeIndex / 2;
  167. while(holeIndex > StartIndex && comp(heapDataVec[parentIndex],adjustValue))
  168. {
  169. heapDataVec[holeIndex] = heapDataVec[parentIndex];
  170. holeIndex = parentIndex;
  171. parentIndex /= 2;
  172. }
  173. heapDataVec[holeIndex] = adjustValue;//将新值放置在正确的位置
  174. }
  175.  
  176. template <class ElemType,class Compare>
  177. void MyHeap<ElemType,Compare>::setNumCounts(int val)
  178. {
  179. numCounts = val;
  180. }

PriorityQueue.h:

  1. #include "Heap.h"
  2.  
  3. //优先级队列类定义
  4. //默认:值最小的权值最大
  5. template <class ElemType,class Compare = less<ElemType> >
  6. class MyPriorityQueue{
  7. private:
  8. MyHeap<ElemType,Compare> heap;//底层用堆实现
  9.  
  10. public:
  11. //构造函数
  12. MyPriorityQueue(ElemType *data,int n);
  13.  
  14. //判断优先级队列是否为空
  15. int empty(){return heap.getVec().size() - 1;}
  16. //返回优先级队列大小
  17. long size(){return heap.getVec().size() - 1;}//注意底层容器第一个元素是无效元素
  18. //取得优先级队列头元素
  19. ElemType top(){return heap.getVec()[StartIndex];}
  20. //添加元素
  21. void push(const ElemType &val);
  22. //弹出队首元素
  23. void pop();
  24. MyHeap<ElemType,Compare>& getHeap(){return heap;};
  25. };
  26.  
  27. template <class ElemType,class Compare>
  28. MyPriorityQueue<ElemType,Compare>::MyPriorityQueue(ElemType *data, int n)
  29. {
  30. heap.initHeap(data,n);
  31. heap.makeHeap();
  32. heap.sortHeap();
  33. }
  34.  
  35. template <class ElemType,class Compare>
  36. void MyPriorityQueue<ElemType,Compare>::push(const ElemType &val)
  37. {
  38. heap.setNumCounts(heap.getVec().size() - 1);//排除容器首部的哨兵元素
  39. heap.makeHeap();
  40. heap.pushHeap(val);
  41. heap.sortHeap();
  42. }
  43.  
  44. template <class ElemType,class Compare>
  45. void MyPriorityQueue<ElemType,Compare>::pop()
  46. {
  47. heap.getVec().erase(heap.getVec().begin() + 1);//删除队列首部的元素
  48. heap.setNumCounts(heap.getVec().size() - 1);//排除容器首部的哨兵元素
  49. heap.makeHeap();
  50. heap.sortHeap();
  51. }

PriorityQueueTest.cpp:

  1. #include "PriorityQueue.h"
  2.  
  3. #include <iostream>
  4. #include <string>
  5.  
  6. using namespace std;
  7.  
  8. int main()
  9. {
  10. const int n = 9;
  11. int data[n] = {0,1,2,3,4,8,9,3,5};
  12. MyPriorityQueue<int> *priorityObj1 = new MyPriorityQueue<int>(data,n);
  13. cout << "Current Heap: " << endl;
  14. for (int i = 1;i <= priorityObj1->size();++i)
  15. {
  16. cout << priorityObj1->getHeap().getVec()[i] << " ";
  17. }
  18. cout << endl;
  19. cout << "Size = " << priorityObj1->size() << endl;
  20. cout << "Top element = " << priorityObj1->top() << endl;
  21. priorityObj1->pop();
  22. cout << "After pop one element:" << endl;
  23. cout << "Size = " << priorityObj1->size() << endl;
  24. cout << "Top element = " << priorityObj1->top() << endl;
  25.  
  26. cout << "Current Heap: " << endl;
  27. for (int i = 1;i <= priorityObj1->size();++i)
  28. {
  29. cout << priorityObj1->getHeap().getVec()[i] << " ";
  30. }
  31. cout << endl;
  32.  
  33. priorityObj1->pop();
  34. cout << "After pop one element:" << endl;
  35. cout << "Size = " << priorityObj1->size() << endl;
  36. cout << "Top element = " << priorityObj1->top() << endl;
  37.  
  38. cout << "Current Heap: " << endl;
  39. for (int i = 1;i <= priorityObj1->size();++i)
  40. {
  41. cout << priorityObj1->getHeap().getVec()[i] << " ";
  42. }
  43. cout << endl;
  44.  
  45. priorityObj1->push(7);
  46. cout << "After push one element 7:" << endl;
  47. cout << "Size = " << priorityObj1->size() << endl;
  48. cout << "Top element = " << priorityObj1->top() << endl;
  49.  
  50. cout << "Current Heap: " << endl;
  51. for (int i = 1;i <= priorityObj1->size();++i)
  52. {
  53. cout << priorityObj1->getHeap().getVec()[i] << " ";
  54. }
  55. cout << endl;
  56.  
  57. delete priorityObj1;
  58. }

运算结果:

STL之heap与优先级队列Priority Queue详解的更多相关文章

  1. 算法与数据结构基础 - 堆(Heap)和优先级队列(Priority queue)

    堆基础 堆(Heap)是具有这样性质的数据结构:1/完全二叉树 2/所有节点的值大于等于(或小于等于)子节点的值: 图片来源:这里 堆可以用数组存储,插入.删除会触发节点shift_down.shif ...

  2. jQuery 源码分析(十一) 队列模块 Queue详解

    队列是常用的数据结构之一,只允许在表的前端(队头)进行删除操作(出队),在表的后端(队尾)进行插入操作(入队).特点是先进先出,最先插入的元素最先被删除. 在jQuery内部,队列模块为动画模块提供基 ...

  3. 什么是Java优先级队列(Priority Queue)?

    PriorityQueue是一个基于优先级堆的无界队列.它的元素是按照自然顺序排序的.在创建元素的时候,我们给它一个一个负责排序的比较器.PriorityQueue不允许null值,因为 它们没有自然 ...

  4. GO语言heap剖析及利用heap实现优先级队列

    GO语言heap剖析 本节内容 heap使用 heap提供的方法 heap源码剖析 利用heap实现优先级队列 1. heap使用 在go语言的标准库container中,实现了三中数据类型:heap ...

  5. Python线程优先级队列(Queue)

    Python的Queue模块中提供了同步的.线程安全的队列类,包括FIFO(先入先出)队列Queue,LIFO(后入先出)队列 LifoQueue,和优先级队列PriorityQueue.这些队列都实 ...

  6. python多线程--优先级队列(Queue)

    Python的Queue模块中提供了同步的.线程安全的队列类,包括FIFO(先入先出)队列Queue,LIFO(后入先出)队列LifoQueue,和优先级队列PriorityQueue.这些队列都实现 ...

  7. 线程优先级队列( Queue)

    Python的Queue模块中提供了同步的.线程安全的队列类,包括FIFO(先入先出)队列Queue,LIFO(后入先出)队列LifoQueue,和优先级队列PriorityQueue.这些队列都实现 ...

  8. STL测试3)优先级队列实现二叉堆

    用法: big_heap.empty();判断堆是否为空 big_heap.pop();弹出栈顶元素最大值 big_heap.push(x);将x添加到最大堆 big_heap.top();返回栈顶元 ...

  9. 2.6 C++STL queue详解

    文章目录 2.6.1 引入 2.6.2 代码示例 2.6.3 代码运行结果 总结 2.6.1 引入 首先,在STL中 queue 和 stack 其实并不叫容器(container),而是叫适配器(a ...

随机推荐

  1. 『转载』hadoop2.x常用端口、定义方法及默认端口

    『转载』hadoop2.x常用端口.定义方法及默认端口 1.问题导读 DataNode的http服务的端口.ipc服务的端口分别是哪个? NameNode的http服务的端口.ipc服务的端口分别是哪 ...

  2. oem 重建

    OracleDBControl启动失败to local from URL=http://your-url.co     方法: emca -deconfig dbcontrol db -repos d ...

  3. WebRTC服务器——Licode 环境搭建

    WebRTC服务器--Licode 环境搭建 系统配置 阿里云服务器 Ubuntu 14.04.5 LTS Docker 环境搭建 在一台空的机器上搭建docker环境,先要安装docker,执行下面 ...

  4. S5PV210 NAND Flash

    NAND Flash 关于NAND FlashS5PV210的NAND Flash控制器有如下特点:1) 支持512byte,2k,4k,8k的页大小2) 通过各种软件模式来进行NAND Flash的 ...

  5. S5PV210串口

    串口设置之输入输出字符 S5PV210 UART相关说明        通用异步收发器简称UART,即UNIVERSAL ASYNCHRONOUS RECEIVER AND TRANSMITTER,它 ...

  6. PYTHON-流程控制之if/while/for-练习

    # 1 练习题## 简述编译型与解释型语言的区别,且分别列出你知道的哪些语言属于编译型,哪些属于解释型# 编译型:C, 谷歌翻译,一次翻译后结果后重复使用# 解释型:Python, 同声传译,边执行边 ...

  7. 解决Javascript中$(window).resize()多次执行

    有些时候,我们需要在浏览器窗口发生变化的时候,动态的执行一些操作,比如做自适应页面时的适配.这个时候,我们需要在窗口拖动的时候去执行代码.但是有些时候,执行的操作比较复杂,我们只希望在窗口拖动完毕之后 ...

  8. BN(Batch Normalization)

    Batch Nornalization Question? 1.是什么? 2.有什么用? 3.怎么用? paper:<Batch Normalization: Accelerating Deep ...

  9. hdu1506单调栈的宽度

    很好的题目,单调栈上的宽度如何求 题解:https://blog.csdn.net/baidu_35643793/article/details/64440095 单调队列和单调栈都是去除没有用的数据 ...

  10. canvas图像保存

    很多时候绘制完成的图片需要保存,那么我们就可以使用到Canvas API来完成这最后一步! Canvas API使用toDataURL方法把绘画的状态输出到一个data URL中然后重新装载,然后我们 ...