[关闭]
@bornkiller 2017-11-14T16:03:07.000000Z 字数 2415 阅读 1636

树遍历算法

前端编程


前言

树是常用的数据结构,Virtual DOM 即标准树结构。后续实现自己的 diff-patch 算法,即建立在树遍历的基础之上,包含深度优先遍历,广度优先遍历。

树遍历

为方便分析,采纳 DOM Tree 作为案例,回避手动构造树结构麻烦,代码如下:

  1. <main class="container" data-traverse-id="bs-container">
  2. <div class="bs-example" data-traverse-id="bs-alerts">
  3. <div class="alert alert-success" role="alert" data-traverse-id="alert-success">
  4. Well done! You successfully read this important alert message.
  5. </div>
  6. <div class="alert alert-info" role="alert" data-traverse-id="alert-info">
  7. Heads up! This alert needs your attention, but it's not super important.
  8. </div>
  9. <div class="alert alert-warning" role="alert" data-traverse-id="alert-warning">
  10. Warning! Better check yourself, you're not looking too good.
  11. </div>
  12. <div class="alert alert-danger" role="alert" data-traverse-id="alert-danger">
  13. Oh snap! Change a few things up and try submitting again.
  14. </div>
  15. </div>
  16. <div class="bs-example" data-traverse-id="bs-list-group">
  17. <ul class="list-group" data-traverse-id="list-group">
  18. <li class="list-group-item text-success" data-traverse-id="text-success">Cras justo odio</li>
  19. <li class="list-group-item text-info" data-traverse-id="text-info">Dapibus ac facilisis in</li>
  20. <li class="list-group-item text-warning" data-traverse-id="text-warning">Morbi leo risus</li>
  21. <li class="list-group-item text-danger" data-traverse-id="text-danger">Porta ac consectetur ac</li>
  22. </ul>
  23. </div>
  24. </main>

DOM Tree 结构抽象如下:

structure.png-59.7kB

使用控制台输出作为简单的遍历操作,代码如下:

  1. /**
  2. * @description - lite operation
  3. *
  4. * @param {HTMLElement} node
  5. */
  6. function operate(node) {
  7. console.log(`Traverse: ${node.getAttribute('data-traverse-id')}`);
  8. }

深度优先遍历递归如下:

  1. /**
  2. * @description - depth-first
  3. *
  4. * @param {HTMLElement} tree
  5. * @param {Function} callback
  6. */
  7. function DFTraverseRecursive(tree, callback) {
  8. if (!tree) {
  9. return;
  10. }
  11. callback(tree);
  12. if (tree.children) {
  13. for (let i = 0; i < tree.childElementCount; i++) {
  14. DFTraverseRecursive(tree.children.item(i), callback)
  15. }
  16. }
  17. }

非递归实现方式如下:

  1. /**
  2. * @description - depth-first
  3. *
  4. * @param {HTMLElement} tree
  5. * @param {Function} callback
  6. */
  7. function DFTraverse(tree, callback) {
  8. let node;
  9. let Queue = [];
  10. Queue.push(tree);
  11. // eslint-disable-next-line
  12. while (node = Queue.pop()) {
  13. callback(node);
  14. if (node.children) {
  15. for (let i = node.childElementCount; i > 0; i--) {
  16. Queue.push(node.children.item(i-1));
  17. }
  18. }
  19. }
  20. }

遍历过程示意如下:

traverse-df.png-69.2kB

广度优先遍历如下:

  1. /**
  2. * @description - depth-first
  3. *
  4. * @param {HTMLElement} tree
  5. * @param {Function} callback
  6. */
  7. function BFTraverse(tree, callback) {
  8. let node;
  9. let Queue = [];
  10. Queue.push(tree);
  11. // eslint-disable-next-line
  12. while (node = Queue.shift()) {
  13. callback(node);
  14. if (node.children) {
  15. for (let i = 0; i < node.childElementCount; i++) {
  16. Queue.push(node.children.item(i));
  17. }
  18. }
  19. }
  20. }

遍历过程示意如下:

traverse-bf.png-72.4kB

Contact

Email: hjj491229492@hotmail.com

qrcode_for_gh_d8efb59259e2_344.jpg-8.7kB

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注