二叉树构造和遍历

客官°小女子只卖身不卖艺 2022-05-28 07:05 273阅读 0赞

今天又看了一遍树的操作,发现二叉树的先序遍历,中序遍历,后序遍历的原理竟然如此简单。虽然以前也会,但是今天找到了更简单的方法。
温故而知新,很好。

  1. /** * Created by BiuBiu_Jiao on 2018/3/31. */
  2. //声明一个节点
  3. function Node(data, left, right) {
  4. this.data = data;
  5. this.left = left;
  6. this.right = right;
  7. this.show = show;
  8. }
  9. function show() {
  10. return this.data;
  11. }
  12. //声明一个二叉树的构造函数
  13. function BST() {
  14. this.root = null;
  15. this.inSert = inSert;
  16. this.inOrder = inOrder;
  17. this.inOrderList = [];
  18. this.preOrder = preOrder;
  19. this.preOrderList = [];
  20. this.afterOrder = afterOrder;
  21. this.afterOrderList = [];
  22. this.generateTree = generateTree;
  23. }
  24. //将一个数组,快速生成二叉树
  25. function generateTree(array) {
  26. if(Array.isArray(array)){
  27. for(let item of array){
  28. this.inSert(item);
  29. }
  30. }
  31. }
  32. //插入节点
  33. function inSert(data) {
  34. var n = new Node(data,null,null);
  35. if(this.root == null){
  36. this.root = n;
  37. }else{
  38. //用两个变量存储root对象的指针,很灵活
  39. var current = this.root;
  40. var parent;
  41. while (true){
  42. parent = current;
  43. if(data < current.data){
  44. current = current.left;
  45. if(current == null){
  46. parent.left = n;
  47. break;
  48. }
  49. //否则叶子节点就是父节点,在下一次循环的时候
  50. }else if(data > current.data){
  51. current = current.right;
  52. if(current == null){
  53. parent.right = n;
  54. break;
  55. }
  56. }else{
  57. //如果相等,就跳出循环
  58. break;
  59. }
  60. }
  61. }
  62. }
  63. //中序遍历
  64. var inOrderList = [];
  65. function inOrder(node,that) {
  66. if(node !== null){
  67. inOrder(node.left,that);
  68. // console.log(node.show()+" ");
  69. that.inOrderList.push(node.show());
  70. inOrder(node.right,that);
  71. }
  72. }
  73. //前(先)序遍历
  74. function preOrder(node,that) {
  75. if(!(node == null)){
  76. // console.log(node.show() + " ");
  77. that.preOrderList.push(node.show());
  78. preOrder(node.left,that);
  79. preOrder(node.right,that);
  80. }
  81. }
  82. //后序遍历
  83. function afterOrder(node,that) {
  84. if(!(node == null)){
  85. afterOrder(node.left,that);
  86. afterOrder(node.right,that);
  87. that.afterOrderList.push(node.show());
  88. // console.log(node.show() + " ");
  89. }
  90. }
  91. var bst = new BST();
  92. let array = [23,45,16,37,3,99,22];
  93. array = [56,22,30,10,81,77,92];
  94. bst.generateTree(array);
  95. bst.inOrder(bst.root,bst);
  96. console.log("inOrderList",bst.inOrderList.toString());
  97. bst.preOrder(bst.root,bst);
  98. console.log("preOrderList",bst.preOrderList.toString());
  99. bst.afterOrder(bst.root,bst);
  100. console.log("afterOrderList",bst.afterOrderList.toString());

结果:

  1. inOrderList 10,22,30,56,77,81,92
  2. preOrderList 56,22,10,30,81,77,92
  3. afterOrderList 10,30,22,77,92,81,56

现在我们说说,温故知新的新,究竟新在哪里?
在此之前,我们要深刻理解,递归到底是什么。
如果你有兴趣的话,不妨再了解一下递归和迭代的区别。
先序遍历
我们可以看到的是,打印节点的语句在最前面,所以这叫先序遍历。
以此类推,中序遍历、后序遍历其实都有类似的结论。
中序遍历,将打印当前节点的语句,放在中间。
后序遍历,将打印当前节点的语句,放在最后。

  1. //前(先)序遍历
  2. function preOrder(node,that) {
  3. if(!(node == null)){
  4. // console.log(node.show() + " ");
  5. that.preOrderList.push(node.show());
  6. preOrder(node.left,that);
  7. preOrder(node.right,that);
  8. }
  9. }

PS:为什么要传指针进去?
因为这是递归调用,当在函数中自己调用自己的时候,没有声明这个方法是谁的(没有用obj.method的方式调用)。因此我们需要将指针传进去。

为什么不适用arguments.callee?
他并不能保证指针的指向是相同的。


发表评论

表情:
评论列表 (有 0 条评论,273人围观)

还没有评论,来说两句吧...

相关阅读

    相关

    前序遍历(左中右)ABDGHCEIF ![前序遍历][70] 中序遍历(左根右)GDHBAEICF![中序遍历][70 1] 后序遍历(左右根)GHDBIEFCA![