类别:二叉排序树

空间效率:O(n)
时间效率:O(log n)内完成插入、查找、删除操作

创造者:Daniel Sleator和Robert Tarjan
优点:每次查询会调整树的结构,使被查询频率高的条目更靠近树根。

注:所有图片来自wiki。

http://blog.csdn.net/cyberzhg/article/details/8058208

Tree Rotation

树的旋转是splay的基础,对于二叉查找树来说,树的旋转不破坏查找树的结构。

Splaying

Splaying是Splay Tree中的基本操作,为了让被查询的条目更接近树根,Splay Tree使用了树的旋转操作,同时保证二叉排序树的性质不变。
Splaying的操作受以下三种因素影响:
  • 节点x是父节点p的左孩子还是右孩子
  • 节点p是不是根节点,如果不是
  • 节点p是父节点g的左孩子还是右孩子
同时有三种基本操作:

Zig Step


当p为根节点时,进行zip step操作。
当x是p的左孩子时,对x右旋;
当x是p的右孩子时,对x左旋。

Zig-Zig Step

当p不是根节点,且x和p同为左孩子或右孩子时进行Zig-Zig操作。
当x和p同为左孩子时,依次将p和x右旋;
当x和p同为右孩子时,依次将p和x左旋。

Zig-Zag Step

当p不是根节点,且x和p不同为左孩子或右孩子时,进行Zig-Zag操作。
当p为左孩子,x为右孩子时,将x左旋后再右旋。
当p为右孩子,x为左孩子时,将x右旋后再左旋。

应用

Splay Tree可以方便的解决一些区间问题,根据不同形状二叉树先序遍历结果不变的特性,可以将区间按顺序建二叉查找树。
每次自下而上的一套splay都可以将x移动到根节点的位置,利用这个特性,可以方便的利用Lazy的思想进行区间操作。
对于每个节点记录size,代表子树中节点的数目,这样就可以很方便地查找区间中的第k小或第k大元素。
对于一段要处理的区间[x, y],首先splay x-1到root,再splay y+1到root的右孩子,这时root的右孩子的左孩子对应子树就是整个区间。
这样,大部分区间问题都可以很方便的解决, 操作同样也适用于一个或多个条目的添加或删除,和区间的移动。

POJ2764 Feed the dogs

http://poj.org/problem?id=2764
http://blog.csdn.net/cyberzhg/article/details/8058154

区间不会重叠,所以不可能有首首相同或尾尾相同的情况,读入所有区间,按照右端由小到大排序。然后通过维护splay进行第k小元素的查询操作。
   
[cpp] view plaincopyprint?
  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. using namespace std;
  5. const int MAXN = 100005;
  6. const int MAXM = 50005;
  7. const int INF = 0x7FFFFFFF;
  8. class SplayTree
  9. {
  10. public:
  11. SplayTree()
  12. {
  13. nil = &_nil;
  14. _nil.value = 0;
  15. _nil.size = 0;
  16. _nil.parent = nil;
  17. _nil.child[LEFT] = nil;
  18. _nil.child[RIGHT] = nil;
  19. }
  20. inline void clear()
  21. {
  22. nodeNumber = 0;
  23. root = nil;
  24. insert(-INF);
  25. insert(INF);
  26. }
  27. inline void insert(const int value)
  28. {
  29. if(root == nil)
  30. {
  31. root = newNode(nil, value);
  32. return;
  33. }
  34. Node *x = root;
  35. while(true)
  36. {
  37. int dir = x->value < value;
  38. if(x->child[dir] == nil)
  39. {
  40. x->child[dir] = newNode(x, value);
  41. update(x);
  42. splay(x->child[dir], nil);
  43. return;
  44. }
  45. else
  46. {
  47. x = x->child[dir];
  48. }
  49. }
  50. }
  51. inline void remove(const int value)
  52. {
  53. int k = find(value);
  54. find(k - 1, nil);
  55. find(k + 1, root);
  56. root->child[RIGHT]->child[LEFT] = nil;
  57. update(root->child[RIGHT]);
  58. update(root);
  59. }
  60. inline int getKth(const int k)
  61. {
  62. find(k + 1, nil);
  63. return root->value;
  64. }
  65. inline void print()
  66. {
  67. printf("Splay Tree: \n");
  68. print(root);
  69. printf("\n");
  70. }private:
  71. static const int LEFT = 0;
  72. static const int RIGHT = 1;
  73. struct Node
  74. {
  75. int value, size;
  76. Node *parent, *child[2];
  77. } _nil, node[MAXN];
  78. int nodeNumber;
  79. Node *root, *nil;
  80. inline Node *newNode(Node *parent, const int value)
  81. {
  82. node[nodeNumber].value = value;
  83. node[nodeNumber].size = 1;
  84. node[nodeNumber].parent = parent;
  85. node[nodeNumber].child[LEFT] = nil;
  86. node[nodeNumber].child[RIGHT] = nil;
  87. return &node[nodeNumber++];
  88. }
  89. inline void update(Node *x)
  90. {
  91. if(x == nil)
  92. {
  93. return;
  94. }
  95. x->size = x->child[LEFT]->size + x->child[RIGHT]->size + 1;
  96. }
  97. inline void rotate(Node *x, const int dir)
  98. {
  99. Node *p = x->parent;
  100. p->child[!dir] = x->child[dir];
  101. p->child[!dir]->parent = p;
  102. x->child[dir] = p;
  103. x->parent = p->parent;
  104. if(p->parent->child[LEFT] == p)
  105. {
  106. p->parent->child[LEFT] = x;
  107. }
  108. else
  109. {
  110. p->parent->child[RIGHT] = x;
  111. }
  112. p->parent = x;
  113. update(p);
  114. update(x);
  115. if(root == p)
  116. {
  117. root = x;
  118. }
  119. }
  120. inline void splay(Node *x, Node *y)
  121. {
  122. while(x->parent != y)
  123. {
  124. if(x->parent->parent == y)
  125. {
  126. if(x->parent->child[LEFT] == x)
  127. {
  128. rotate(x, RIGHT);
  129. }
  130. else
  131. {
  132. rotate(x, LEFT);
  133. }
  134. }
  135. else if(x->parent->parent->child[LEFT] == x->parent)
  136. {
  137. if(x->parent->child[LEFT] == x)
  138. {
  139. rotate(x->parent, RIGHT);
  140. rotate(x, RIGHT);
  141. }
  142. else
  143. {
  144. rotate(x, LEFT);
  145. rotate(x, RIGHT);
  146. }
  147. }
  148. else
  149. {
  150. if(x->parent->child[RIGHT] == x)
  151. {
  152. rotate(x->parent, LEFT);
  153. rotate(x, LEFT);
  154. }
  155. else
  156. {
  157. rotate(x, RIGHT);
  158. rotate(x, LEFT);
  159. }
  160. }
  161. update(x);
  162. }
  163. }
  164. inline void find(int k, Node *y)
  165. {
  166. Node *x = root;
  167. while(k != x->child[LEFT]->size + 1)
  168. {
  169. if(k <= x->child[LEFT]->size)
  170. {
  171. x = x->child[LEFT];
  172. }
  173. else
  174. {
  175. k -= x->child[LEFT]->size + 1;
  176. x = x->child[RIGHT];
  177. }
  178. }
  179. splay(x, y);
  180. }
  181. inline int find(const int value)
  182. {
  183. Node *x = root;
  184. int count = 0;
  185. while(true)
  186. {
  187. if(x->value == value)
  188. {
  189. return count + x->size - x->child[RIGHT]->size;
  190. }
  191. else if(x->value > value)
  192. {
  193. x = x->child[LEFT];
  194. }
  195. else
  196. {
  197. count += x->size - x->child[RIGHT]->size;
  198. x = x->child[RIGHT];
  199. }
  200. }
  201. }
  202. inline void print(Node *x)
  203. {
  204. if(x == nil)
  205. {
  206. return;
  207. }
  208. printf("%d: %d %d %d\n", x->value, x->child[LEFT]->value, x->child[RIGHT]->value, x->size);
  209. print(x->child[LEFT]);
  210. print(x->child[RIGHT]);
  211. }
  212. } splay;
  213. struct Interval
  214. {
  215. int a, b, k, index;
  216. bool operator < (const Interval &interval) const
  217. {
  218. return b < interval.b;
  219. }
  220. } interval[MAXM];int pretty[MAXN];int ans[MAXM];
  221. int main()
  222. {
  223. int n, m;
  224. while(~scanf("%d%d", &n, &m))
  225. {
  226. for(int i=1;i<=n;++i)
  227. {
  228. scanf("%d", &pretty[i]);
  229. }
  230. for(int i=0;i<m;++i)
  231. {
  232. scanf("%d%d%d", &interval[i].a, &interval[i].b, &interval[i].k);
  233. interval[i].index = i;
  234. }
  235. sort(interval, interval + m);
  236. splay.clear();
  237. int a = 1, b = 0;
  238. for(int i=0;i<m;++i)
  239. {
  240. for(int j=a;j<interval[i].a && j<=b;++j)
  241. {
  242. splay.remove(pretty[j]);
  243. }
  244. for(int j=max(interval[i].a, b+1);j<=interval[i].b;++j)
  245. {
  246. splay.insert(pretty[j]);
  247. }
  248. a = interval[i].a;
  249. b = interval[i].b;
  250. ans[interval[i].index] = splay.getKth(interval[i].k);
  251. }
  252. for(int i=0;i<m;++i)
  253. {
  254. printf("%d\n", ans[i]);
  255. }
  256. }
  257. return 0;
  258. }


POJ3580 SuperMemo

http://poj.org/problem?id=3580
http://blog.csdn.net/cyberzhg/article/details/8053293
在序列首尾加上值为INF的点。一共六种操作:
1. ADD x y D
将x到y区间加上D。
利用lazy。将x-1位置splay到root,y+1位置splay到root的右孩子,这时y+1位置的左孩子就是区间的范围。
2. REVERSE x y 反转x到y区间
和ADD类似,记录区间是否反转,在需要的时候调换左右孩子。
3. REVOLVE x y T 将x到y区间循环右移T次
DELETE和INSERT的综合,两次区间操作。
4. INSERT x P 在x位置后插入P
和ADD类似,将区间设为空,插入新的数值。
5. DELETE x 删除x位置的数
和ADD类似,将最终区间设为空。
6. MIN x y 求x到y区间中的最小值
和ADD类似,记录所有子树的min,在旋转的过程中更新。
   
[cpp] view plaincopyprint?
  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. using namespace std;
  5. const int MAXN = 100005;
  6. const int MAXM = 100005;
  7. const int INF = 0x7fffffff;
  8. class SplayTree
  9. {
  10. public:
  11. SplayTree()
  12. {
  13. nil.size = 0;
  14. nil.value = INF;
  15. nil.min = INF;
  16. nil.lchild = &nil;
  17. nil.rchild = &nil;
  18. nil.parent = &nil;
  19. }
  20. inline void make(int array[], int n)
  21. {
  22. nodeNumber = 0;
  23. int mid = (n - 1) >> 1;
  24. root = newNode(&nil, array[mid]);
  25. root->lchild = make(0, mid - 1, root, array);
  26. root->rchild = make(mid + 1, n - 1, root, array);
  27. update(root);
  28. }
  29. inline void ADD(int x, int y, int D)
  30. {
  31. find(x, &nil);
  32. find(y + 2, root);
  33. root->rchild->lchild->lazy += D;
  34. }
  35. inline void REVERSE(int x, int y)
  36. {
  37. find(x, &nil);
  38. find(y + 2, root);
  39. root->rchild->lchild->isReverse ^= true;
  40. }
  41. inline void REVOLVE(int x, int y, int T)
  42. {
  43. int len = y - x + 1;
  44. T = ((T % len) + len) % len;
  45. if(T)
  46. {
  47. find(y - T + 1, &nil);
  48. find(y + 2, root);
  49. SplayNode *d = root->rchild->lchild;
  50. root->rchild->lchild = &nil;
  51. find(x, &nil);
  52. find(x + 1, root);
  53. root->rchild->lchild = d;
  54. d->parent = root->rchild;
  55. }
  56. }
  57. inline void INSERT(int x, int P)
  58. {
  59. find(x + 1, &nil);
  60. find(x + 2, root);
  61. root->rchild->lchild = newNode(root->rchild, P);
  62. }
  63. inline void DELETE(int x)
  64. {
  65. find(x, &nil);
  66. find(x + 2, root);
  67. root->rchild->lchild = &nil;
  68. }
  69. inline void MIN(int x, int y)
  70. {
  71. find(x, &nil);
  72. find(y + 2, root);
  73. pushdown(root->rchild->lchild);
  74. printf("%d\n", root->rchild->lchild->min);
  75. }
  76. inline void print()
  77. {
  78. printf("Splay Linear: \n");
  79. print(root);
  80. printf("\n");
  81. }
  82. inline void prints()
  83. {
  84. printf("Splay Structure: \n");
  85. prints(root);
  86. printf("\n");
  87. }
  88. private:
  89. struct SplayNode
  90. {
  91. int value, size, lazy;
  92. SplayNode *parent, *lchild, *rchild;
  93. int min;
  94. bool isReverse;
  95. } nil, node[MAXN + MAXM];
  96. int nodeNumber;
  97. SplayNode *root;
  98. inline SplayNode *newNode(SplayNode *parent, const int value)
  99. {
  100. node[nodeNumber].value = value;
  101. node[nodeNumber].size = 1;
  102. node[nodeNumber].lazy = 0;
  103. node[nodeNumber].parent = parent;
  104. node[nodeNumber].lchild = &nil;
  105. node[nodeNumber].rchild = &nil;
  106. node[nodeNumber].min = value;
  107. node[nodeNumber].isReverse = false;
  108. return &node[nodeNumber++];
  109. }
  110. SplayNode *make(int l, int r, SplayNode *parent, int array[])
  111. {
  112. if(l > r)
  113. {
  114. return &nil;
  115. }
  116. int mid = (l + r) >> 1;
  117. SplayNode *x = newNode(parent, array[mid]);
  118. x->lchild = make(l, mid - 1, x, array);
  119. x->rchild = make(mid + 1, r, x, array);
  120. update(x);
  121. return x;
  122. }
  123. inline void update(SplayNode *x)
  124. {
  125. if(x == &nil)
  126. {
  127. return;
  128. }
  129. x->size = x->lchild->size + x->rchild->size + 1;
  130. x->min = min(x->value, min(x->lchild->min, x->rchild->min));
  131. }
  132. inline void pushdown(SplayNode *x)
  133. {
  134. if(x == &nil)
  135. {
  136. return;
  137. }
  138. if(x->isReverse)
  139. {
  140. swap(x->lchild, x->rchild);
  141. x->lchild->isReverse ^= true;
  142. x->rchild->isReverse ^= true;
  143. x->isReverse = false;
  144. }
  145. if(x->lazy)
  146. {
  147. x->value += x->lazy;
  148. x->min += x->lazy;
  149. x->lchild->lazy += x->lazy;
  150. x->rchild->lazy += x->lazy;
  151. x->lazy = 0;
  152. }
  153. }
  154. inline void rotateLeft(SplayNode *x)
  155. {
  156. SplayNode *p = x->parent;
  157. pushdown(x->lchild);
  158. pushdown(x->rchild);
  159. pushdown(p->lchild);
  160. p->rchild = x->lchild;
  161. p->rchild->parent = p;
  162. x->lchild = p;
  163. x->parent = p->parent;
  164. if(p->parent->lchild == p)
  165. {
  166. p->parent->lchild = x;
  167. }
  168. else
  169. {
  170. p->parent->rchild = x;
  171. }
  172. p->parent = x;
  173. update(p);
  174. update(x);
  175. if(root == p)
  176. {
  177. root = x;
  178. }
  179. }
  180. inline void rotateRight(SplayNode *x)
  181. {
  182. SplayNode *p = x->parent;
  183. pushdown(x->lchild);
  184. pushdown(x->rchild);
  185. pushdown(p->rchild);
  186. p->lchild = x->rchild;
  187. p->lchild->parent = p;
  188. x->rchild = p;
  189. x->parent = p->parent;
  190. if(p->parent->lchild == p)
  191. {
  192. p->parent->lchild = x;
  193. }
  194. else
  195. {
  196. p->parent->rchild = x;
  197. }
  198. p->parent = x;
  199. update(p);
  200. update(x);
  201. if(root == p)
  202. {
  203. root = x;
  204. }
  205. }
  206. inline void splay(SplayNode *x, SplayNode *y)
  207. {
  208. pushdown(x);
  209. while(x->parent != y)
  210. {
  211. if(x->parent->parent == y)
  212. {
  213. if(x->parent->lchild == x)
  214. {
  215. rotateRight(x);
  216. }
  217. else
  218. {
  219. rotateLeft(x);
  220. }
  221. }
  222. else if(x->parent->parent->lchild == x->parent)
  223. {
  224. if(x->parent->lchild == x)
  225. {
  226. rotateRight(x->parent);
  227. rotateRight(x);
  228. }
  229. else
  230. {
  231. rotateLeft(x);
  232. rotateRight(x);
  233. }
  234. }
  235. else
  236. {
  237. if(x->parent->rchild == x)
  238. {
  239. rotateLeft(x->parent);
  240. rotateLeft(x);
  241. }
  242. else
  243. {
  244. rotateRight(x);
  245. rotateLeft(x);
  246. }
  247. }
  248. }
  249. update(x);
  250. }
  251. inline void find(int k, SplayNode *y)
  252. {
  253. SplayNode *x = root;
  254. pushdown(x);
  255. while(k != x->lchild->size + 1)
  256. {
  257. if(k <= x->lchild->size)
  258. {
  259. x = x->lchild;
  260. }
  261. else
  262. {
  263. k -= x->lchild->size + 1;
  264. x = x->rchild;
  265. }
  266. pushdown(x);
  267. }
  268. splay(x, y);
  269. }
  270. inline void print(SplayNode *x)
  271. {
  272. if(x == &nil)
  273. {
  274. return;
  275. }
  276. pushdown(x);
  277. print(x->lchild);
  278. printf("%d: %d %d %d %d\n", x->value, x->min, x->parent->value, x->lchild->value, x->rchild->value);
  279. print(x->rchild);
  280. }
  281. inline void prints(SplayNode *x)
  282. {
  283. if(x == &nil)
  284. {
  285. return;
  286. }
  287. pushdown(x);
  288. if(x->value == INF)
  289. {
  290. printf("INF : ");
  291. }
  292. else
  293. {
  294. printf("%d : ", x->value);
  295. }
  296. if(x->lchild == &nil)
  297. {
  298. printf("nil ");
  299. }
  300. else
  301. {
  302. if(x->lchild->value == INF)
  303. {
  304. printf("INF ");
  305. }
  306. else
  307. {
  308. printf("%d ", x->lchild->value);
  309. }
  310. }
  311. if(x->rchild == &nil)
  312. {
  313. printf("nil\n");
  314. }
  315. else
  316. {
  317. if(x->rchild->value == INF)
  318. {
  319. printf("INF\n");
  320. }
  321. else
  322. {
  323. printf("%d\n", x->rchild->value);
  324. }
  325. }
  326. prints(x->lchild);
  327. prints(x->rchild);
  328. }
  329. } splayTree;
  330. char buffer[128];int array[MAXN];int n, m;
  331. int main()
  332. {
  333. int x, y, D, T, P;
  334. scanf("%d", &n);
  335. for(int i=1;i<=n;++i)
  336. {
  337. scanf("%d", &array[i]);
  338. }
  339. array[0] = INF;
  340. array[n+1] = INF;
  341. splayTree.make(array, n + 2);
  342. scanf("%d", &m);
  343. while(m--)
  344. {
  345. scanf("%s", buffer);
  346. switch(buffer[0])
  347. {
  348. case 'A':
  349. scanf("%d%d%d", &x, &y, &D);
  350. splayTree.ADD(x, y, D);
  351. break;
  352. case 'R':
  353. if('E' == buffer[3])
  354. {
  355. scanf("%d%d", &x, &y);
  356. splayTree.REVERSE(x, y);
  357. }
  358. else
  359. {
  360. scanf("%d%d%d", &x, &y, &T);
  361. splayTree.REVOLVE(x, y, T);
  362. }
  363. break;
  364. case 'I':
  365. scanf("%d%d", &x, &P);
  366. splayTree.INSERT(x, P);
  367. break;
  368. case 'D':
  369. scanf("%d", &x);
  370. splayTree.DELETE(x);
  371. break;
  372. case 'M':
  373. scanf("%d%d", &x, &y);
  374. splayTree.MIN(x, y);
  375. break;
  376. }
  377. }
  378. return 0;
  379. }

Splay Tree相关推荐

  1. BZOJ1500 [NOI2005]维修数列(Splay tree)

    [Submit][Status][Discuss] Description 请写一个程序,要求维护一个数列,支持以下 6 种操作: 请注意,格式栏 中的下划线' _ '表示实际输入文件中的空格 Inp ...

  2. 伸展树(Splay tree)图解与实现

    伸展树(Splay tree)图解与实现 伸展树(Splay tree)图解与实现_小张的专栏-CSDN博客_splay树 Splay树详解 Splay树详解 - 秦淮岸灯火阑珊 - 博客园 平衡树 ...

  3. poj 2892 Tunnel Warfare (Splay Tree instead of Segment Tree)

    poj.org/problem?id=2892 poj上的一道数据结构题,这题正解貌似是Segment Tree,不过我用了Splay Tree来写,而且我个人认为,这题用Splay Tree会更好写 ...

  4. [HNOI2002]营业额统计 Splay tree入门题

    [HNOI2002]营业额统计 题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1588 [HNOI2002]营业额统计 Time Limit ...

  5. splay tree java移除_Splay Tree的删除操作

    Splay Tree的插入操作,搜索操作,和删除操作都实现了,那么就能够使用来解题了. 指针的删除操作的处理还是那么难的,非常多坎须要避开. 同一个坎还是坑了我好多次,就是指针传递的问题,什么时候须要 ...

  6. splay tree java_伸展树(splay tree)自顶向下的算法

    伸展树(splay tree)是一种能自我调整的二叉搜索树(BST).虽然某一次的访问操作所花费的时间比较长,但是平摊(amortized) 之后的访问操作(例如旋转)时间能达到O(logn)的复杂度 ...

  7. 伸展树(Splay Tree)尽收眼底

    原文地址:http://dsqiu.iteye.com/blog/1706592 伸展树(Splay Tree)尽收眼底 本文内容框架: §1 伸展树定义 §2 伸展树自底向上伸展   §3 伸展树自 ...

  8. 伸展树(Splay tree)浅谈

    树看的越来越多,越来越神奇. 看伸展树这种神级数据结构之前,建议大家首先彻底明白二叉搜索树,这是万树的基础. 然后可以去看下treap,最好再去看下红黑树.如果有线段树的基础那更好了,我们会发现线段树 ...

  9. Splay Tree伸展树

    伸展树基本概念 伸展树的基本思想. 伸展树完全是基于局部性原理(locality)的. 局部性原理是计算机科学中非常重要的原理,很多设计,比如说多级存储器,缓存,都是基于局部性原理.简单说来就是< ...

最新文章

  1. PHP Session中保存Object
  2. mysql登录之后可以写什么_MYSQL登陆完之后如何操作???(新手求助)
  3. 谈谈关于MVP模式中V-P交互问题
  4. 使用ASP.NET 2.0 Profile存储用户信息
  5. Java集合系列---List源码解析(ArrayList和LinkedList的区别)
  6. PMOS 和 NMOS区别
  7. java 蓝桥杯算法训练 未名湖边的烦恼
  8. Java基础——基本类型和包装类、基本类型和字符串之间的转换
  9. 拓端tecdat|R语言GARCH-DCC模型和DCC(MVT)建模估计
  10. [转载] 中华典故故事(孙刚)——33 人上一百形形色色
  11. 程序员面试宝典及Java面试题解析2021年
  12. django+layui表格数据管理
  13. 记录一下3dmax--substancePainter-unity烘焙法线详细过程
  14. 数据结构——图的邻接矩阵实现
  15. 【产品】设计时可用到的认知偏差与效应
  16. 如何选择终端桌面管理软件?
  17. unity球体添加光源_关于Unity中的光源
  18. 小猿君的面试细节课堂(第二节)
  19. DefCampCTF2122取证
  20. 安装Souce Insight 4.0 、显示文件浏览、折叠代码

热门文章

  1. BUUCTF NewStarCTF 公开赛赛道Week3 Writeup
  2. table的样式设置
  3. 记一个chrome自带input:-internal-autofill-selected背景色样式问题
  4. Matlab中meshgrid的用法
  5. old DIB in res XXX ico pass it through SDKPAINT 错误
  6. Cookie是什么及用法详解
  7. 【图像处理】相机成像原理
  8. usleep()和sleep()的区别
  9. Linux查看全部进程的命令
  10. WebGIS第九课:智慧校园项目(1)