javascript数据结构与算法-- 二叉树

树是计算机科学中经常用到的一种数据结构。树是一种非线性的数据结构,以分成的方式存储数据,树被用来存储具有层级关系的数据,比如文件系统的文件,树还被用来存储有序列表。我们要研究的是二叉树,在二叉树上查找元素非常快,为二叉树添加元素或者删除元素,也是非常快的。

树的基本结构示意图如下:

我们现在最主要的是要来学习二叉树,二叉树是一种特殊的树,它的特征是 子节点个数不超过2个。如下图就是二叉树的基本结构示意图如下:

二叉树是一种特殊的树,相对较少的值保存在左节点上,较大的值保存在右节点中。这一特性使得查找的效率非常高,对于数值型和非数值型的数据,比如单词和字符串都是一样。

下面我们来学习插入节点的操作吧!

1.   二叉树是由节点组成的,所以我们需要定义一个对象node,可以保存数据,也可以保存其他节点的链接(left 和 right),show()方法用来显示保存在节点中的数据。Node代码如下:

  1. function Node(data,left,right) {
  2. this.data = data;
  3. this.left = left;
  4. this.right = right;
  5. this.show = show;
  6. }

插入节点分析如下:

代码如下:

  1. function Node(data,left,right) {
  2. this.data = data;
  3. this.left = left;
  4. this.right = right;
  5. this.show = show;
  6. }
  7. function show() {
  8. return this.data;
  9. }
  10. function BST() {
  11. this.root = null;
  12. this.insert = insert;
  13. this.inOrder = inOrder;
  14. }
  15. function insert(data) {
  16. var n = new Node(data,null,null);
  17. if(this.root == null) {
  18. this.root = n;
  19. }else {
  20. var current = this.root;
  21. var parent;
  22. while(current) {
  23. parent = current;
  24. if(data < current.data) {
  25. current = current.left;
  26. if(current == null) {
  27. parent.left = n;
  28. break;
  29. }
  30. }else {
  31. current = current.right;
  32. if(current == null) {
  33. parent.right = n;
  34. break;
  35. }
  36. }
  37. }
  38. }
  39. }
  40. 初始代码如下:
  41. var nums = new BST();
  42. nums.insert(23);
  43. nums.insert(45);
  44. nums.insert(16);
  45. nums.insert(37);
  46. nums.insert(3);
  47. nums.insert(99);
  48. nums.insert(22);

示意图如下:

1. 执行insert(23)时候,由于根节点== null 所以 根节点为23.

2. 执行insert(45)的时候,根节点不等于null,因此进入while语句;由于45 > 大于根节点23 所以就进入else语句,当前current的值如下图:

当执行 current = current.right; 这句代码时候,当前current值变为null了,然后进行if判断代码如下:

  1. if(current == null) {
  2. parent.right = n;
  3. break;
  4.  
  5. }

所以45为根节点的右节点了。跳出循环语句;

3. 执行insert(16)的时候,根节点不等于null,因此进入while语句,由于16 < 小于根节点23,所以就进入if语句,那么当前的current值如下:

当执行到 current = current.left; 的时候,current的值就变为null,所以接着往下执行代码:

  1. if(current == null) {
  2. parent.left = n;
  3. break;
  4. }

就把当前的节点16插入到根节点的左节点上。

4. 接着执行 insert(37) 的时候,根节点不等于null,因此进入else语句中的while语句,由于37 大于根节点23,所以就进入while语句中的else语句,当前的current值为:

当执行current = current.right;这句代码的时候,那么当前current = 45的那个节点(如上图所示);当再执行下面的代码:

  1. if(current == null) {
  2. parent.right = n;
  3. break;
  4. }

那么current != null 所以接着进入下一次while循环,执行这句代码后;parent = current;

那么parent = 45的那个节点了,current值如下所示:

接着进入if语句判断,由于当前的根节点是45,所以37 小于根节点 45了,所以就进入if语句代码如下:

  1. if(data < current.data) {
  2. current = current.left;
  3. if(current == null) {
  4. parent.left = n;
  5. break;
  6. }
  7. }

Current = current.left 因此current = null; 继续执行上面的if语句判断是否为null的时候,因此就把37放入根节点为45的左节点上了。

5. 直接执行insert(3); 的时候,根节点不为空,所以就进入else语句的while语句中,由于当前的data = 3,所以执行如下if判断代码:

  1. if(data < current.data) {
  2. current = current.left;
  3. if(current == null) {
  4. parent.left = n;
  5. break;
  6. }
  7. }

插入的节点值3 小于 根节点23,进入if语句里面执行,但是当前的current值如下:

所以当执行 current = current.left 的时候,那么current = 16的那个节点了,如下所示:

因此current 不等于null,所以就执行到下一次while循环,继续进入while中的if判断,由于当前的根节点是16,所以也就进入了if里面的代码去执行,在执行这句代码后:

current = current.left; 由上图可知:current = null;current就等于null了;再执行代码如下:

  1. if(current == null) {
  2. parent.left = n;
  3. break;
  4. }

就把节点3 插入到当前的根节点为16的左节点了。

6. 执行insert(99)的时候;当前的根节点23 小于 99,那么就进入else语句了,那么current值就等于如下:

当执行 current = current.right; 的时候 ,那么current 就等于如下:

再接着执行代码:

  1. if(current == null) {
  2. parent.right = n;
  3. break;
  4. }

如上图所示,current并不等于null,所以执行下一次while循环,继续进入while中的else语句,那么当前的current值如下:

当执行current = current.right;这句代码的时候,那么current 就等于 null了,所以执行if语句代码如下:

  1. if(current == null) {
  2. parent.right = n;
  3. break;
  4. }

就把99节点插入到当前的根节点为45节点的右节点了。

7. 执行 insert(22);的时候,由于根节点为23,所以节点22 小于 23,所以进入while中的if语句里面了,那么当前current值如下:

当执行 current = current.left; 的时候,那么current值变为如下所示:

所以执行 if语句代码如下:

  1. if(current == null) {
  2. parent.left = n;
  3. break;
  4. }

不等于null,所以斤进入while下一次循环,由于当前的根节点16 小于插入的节点22 ,所以就进入else语句了,那么当前的current值如下:

再执行这句代码 current = current.right; 那么current就等于null了;因此就把节点22插入到根节点为16上面的右节点上了;

以上是插入节点的整个流程!

二:遍历二叉查找树;

遍历二叉树的方法有三种,中序,先序和后序。

1. 中序;

如下图所示:

中序遍历使用递归的方式实现,该方法需要以升序访问树中的所有节点,先访问左子树,再访问根节点,最后访问右子树。

代码如下:

  1. // 中序遍历
  2. function inOrder(node) {
  3. if(!(node == null)) {
  4. inOrder(node.left);
  5. console.log(node.show());
  6. inOrder(node.right);
  7. }
  8. }

代码分析如下:

JS所有代码如下:

  1. function Node(data,left,right) {
  2. this.data = data;
  3. this.left = left;
  4. this.right = right;
  5. this.show = show;
  6. }
  7.  
  8. function show() {
  9. return this.data;
  10. }
  11.  
  12. function BST() {
  13. this.root = null;
  14. this.insert = insert;
  15. this.inOrder = inOrder;
  16. }
  17.  
  18. function insert(data) {
  19. var n = new Node(data,null,null);
  20. if(this.root == null) {
  21. this.root = n;
  22. }else {
  23. var current = this.root;
  24. var parent;
  25. while(current) {
  26. parent = current;
  27. if(data < current.data) {
  28. current = current.left;
  29. if(current == null) {
  30. parent.left = n;
  31. break;
  32. }
  33. }else {
  34. current = current.right;
  35. if(current == null) {
  36. parent.right = n;
  37. break;
  38. }
  39. }
  40. }
  41. }
  42. }
  43. // 中序遍历
  44. function inOrder(node) {
  45. if(!(node == null)) {
  46. inOrder(node.left);
  47. console.log(node.show());
  48. inOrder(node.right);
  49. }
  50. }
  51. 代码初始化如下:
  52. var nums = new BST();
  53. nums.insert(23);
  54. nums.insert(45);
  55. nums.insert(16);
  56. nums.insert(37);
  57. nums.insert(3);
  58. nums.insert(99);
  59. nums.insert(22);
  60. inOrder(nums.root);

2. 先序:先序遍历先访问根节点,然后以同样方式访问左子树和右子树。如下图所示:

代码如下:

  1. // 先序遍历
  2. function preOrder(node) {
  3. if(!(node == null)) {
  4. console.log(node.show());
  5. preOrder(node.left);
  6. preOrder(node.right);
  7. }
  8. }

JS所有代码如下:

  1. function Node(data,left,right) {
  2. this.data = data;
  3. this.left = left;
  4. this.right = right;
  5. this.show = show;
  6. }
  7. function show() {
  8. return this.data;
  9. }
  10. function BST() {
  11. this.root = null;
  12. this.insert = insert;
  13. this.inOrder = inOrder;
  14. }
  15. function insert(data) {
  16. var n = new Node(data,null,null);
  17. if(this.root == null) {
  18. this.root = n;
  19. }else {
  20. var current = this.root;
  21. var parent;
  22. while(current) {
  23. parent = current;
  24. if(data < current.data) {
  25. current = current.left;
  26. if(current == null) {
  27. parent.left = n;
  28. break;
  29. }
  30. }else {
  31. current = current.right;
  32. if(current == null) {
  33. parent.right = n;
  34. break;
  35. }
  36. }
  37. }
  38. }
  39. }
  40. // 中序遍历
  41. function inOrder(node) {
  42. if(!(node == null)) {
  43. inOrder(node.left);
  44. console.log(node.show());
  45. inOrder(node.right);
  46. }
  47. }
  48.  
  49. // 先序遍历
  50. function preOrder(node) {
  51. if(!(node == null)) {
  52. console.log(node.show());
  53. preOrder(node.left);
  54. preOrder(node.right);
  55. }
  56. }
  57. 初始化代码如下:
  58. var nums = new BST();
  59. nums.insert(23);
  60. nums.insert(45);
  61. nums.insert(16);
  62. nums.insert(37);
  63. nums.insert(3);
  64. nums.insert(99);
  65. nums.insert(22);
  66. console.log("--------------");
  67. preOrder(nums.root);

先序遍历打印如下:

3. 后序:后序遍历先访问叶子节点,从左子树到右子树,再到根节点,如下所示:

JS代码如下:

  1. // 后序遍历
  2. function postOrder(node) {
  3. if(!(node == null)) {
  4. postOrder(node.left);
  5. postOrder(node.right);
  6. console.log("后序遍历"+node.show());
  7. }
  8. }

所有的JS代码如下:

  1. function Node(data,left,right) {
  2. this.data = data;
  3. this.left = left;
  4. this.right = right;
  5. this.show = show;
  6. }
  7.  
  8. function show() {
  9. return this.data;
  10. }
  11.  
  12. function BST() {
  13. this.root = null;
  14. this.insert = insert;
  15. this.inOrder = inOrder;
  16. }
  17.  
  18. function insert(data) {
  19. var n = new Node(data,null,null);
  20. if(this.root == null) {
  21. this.root = n;
  22. }else {
  23. var current = this.root;
  24. var parent;
  25. while(current) {
  26. parent = current;
  27. if(data < current.data) {
  28. current = current.left;
  29. if(current == null) {
  30. parent.left = n;
  31. break;
  32. }
  33. }else {
  34. current = current.right;
  35. if(current == null) {
  36. parent.right = n;
  37. break;
  38. }
  39. }
  40. }
  41. }
  42. }
  43. // 中序遍历
  44. function inOrder(node) {
  45. if(!(node == null)) {
  46. inOrder(node.left);
  47. console.log(node.show());
  48. inOrder(node.right);
  49. }
  50. }
  51.  
  52. // 先序遍历
  53. function preOrder(node) {
  54. if(!(node == null)) {
  55. console.log(node.show());
  56. preOrder(node.left);
  57. preOrder(node.right);
  58. }
  59. }
  60.  
  61. // 后序遍历
  62. function postOrder(node) {
  63. if(!(node == null)) {
  64. postOrder(node.left);
  65. postOrder(node.right);
  66. console.log("后序遍历"+node.show());
  67. }
  68. }
  69. 页面初始化如下:
  70. var nums = new BST();
  71. nums.insert(23);
  72. nums.insert(45);
  73. nums.insert(16);
  74. nums.insert(37);
  75. nums.insert(3);
  76. nums.insert(99);
  77. nums.insert(22);
  78. console.log("--------------");
  79. postOrder(nums.root);

打印如下:

在二叉查找树上进行查找

查找二叉树上的最小值与最大值非常简单,因为较小的值总是在左子节点上,在二叉树上查找最小值,只需要遍历左子树,直到找到最后一个节点。

1. 二叉树查找最小值

代码如下:

  1. // 二叉树查找最小值
  2. function getMin(){
  3. var current = this.root;
  4. while(!(current.left == null)) {
  5. current = current.left;
  6. }
  7. return current.data;
  8. }

所有JS代码如下:

  1. function Node(data,left,right) {
  2. this.data = data;
  3. this.left = left;
  4. this.right = right;
  5. this.show = show;
  6. }
  7.  
  8. function show() {
  9. return this.data;
  10. }
  11.  
  12. function BST() {
  13. this.root = null;
  14. this.insert = insert;
  15. this.inOrder = inOrder;
  16. this.getMin = getMin;
  17. }
  18.  
  19. function insert(data) {
  20. var n = new Node(data,null,null);
  21. if(this.root == null) {
  22. this.root = n;
  23. }else {
  24. var current = this.root;
  25. var parent;
  26. while(current) {
  27. parent = current;
  28. if(data < current.data) {
  29. current = current.left;
  30. if(current == null) {
  31. parent.left = n;
  32. break;
  33. }
  34. }else {
  35. current = current.right;
  36. if(current == null) {
  37. parent.right = n;
  38. break;
  39. }
  40. }
  41. }
  42. }
  43. }
  44. // 中序遍历
  45. function inOrder(node) {
  46. if(!(node == null)) {
  47. inOrder(node.left);
  48. console.log(node.show());
  49. inOrder(node.right);
  50. }
  51. }
  52.  
  53. // 先序遍历
  54. function preOrder(node) {
  55. if(!(node == null)) {
  56. console.log(node.show());
  57. preOrder(node.left);
  58. preOrder(node.right);
  59. }
  60. }
  61.  
  62. // 后序遍历
  63. function postOrder(node) {
  64. if(!(node == null)) {
  65. postOrder(node.left);
  66. postOrder(node.right);
  67. console.log("后序遍历"+node.show());
  68. }
  69. }
  70.  
  71. // 二叉树查找最小值
  72. function getMin(){
  73. var current = this.root;
  74. while(!(current.left == null)) {
  75. current = current.left;
  76. }
  77. return current.data;
  78. }
  79. 测试代码初始化如下:
  80. var nums = new BST();
  81. nums.insert(23);
  82. nums.insert(45);
  83. nums.insert(16);
  84. nums.insert(37);
  85. nums.insert(3);
  86. nums.insert(99);
  87. nums.insert(22);
  88. var min = nums.getMin();
  89. console.log(min); // 打印出3

代码分析如下:

1 当执行到getMin()方法内的 var current = this.root的时候,当前的this.root的值为如下:

因此进入while内的循环,执行到代码:

current = current.left,current.left值如下:

赋值给current,因此current等于上面的节点。接着继续循环遍历while,执行到代码 current = current.left , current.left值变成如下:

然后值赋值给current。再继续遍历,进入while循环,while(!(current.left == null)) {}代码判断,由上图可知;current.left = null,因此就跳出整个while循环,因此打印3出来。

2.在二叉树上查找最大值;只需遍历右子树,直到查到最后一个节点,该节点上保存的值即为最大值。

JS代码如下:

  1. // 二叉树上查找最大值
  2. function getMax() {
  3. var current = this.root;
  4. while(!(current.right == null)) {
  5. current = current.right;
  6. }
  7. return current.data;
  8. }

下面是所有的JS代码:

  1. function Node(data,left,right) {
  2. this.data = data;
  3. this.left = left;
  4. this.right = right;
  5. this.show = show;
  6. }
  7.  
  8. function show() {
  9. return this.data;
  10. }
  11.  
  12. function BST() {
  13. this.root = null;
  14. this.insert = insert;
  15. this.inOrder = inOrder;
  16. this.getMin = getMin;
  17. this.getMax = getMax;
  18. }
  19.  
  20. function insert(data) {
  21. var n = new Node(data,null,null);
  22. if(this.root == null) {
  23. this.root = n;
  24. }else {
  25. var current = this.root;
  26. var parent;
  27. while(current) {
  28. parent = current;
  29. if(data < current.data) {
  30. current = current.left;
  31. if(current == null) {
  32. parent.left = n;
  33. break;
  34. }
  35. }else {
  36. current = current.right;
  37. if(current == null) {
  38. parent.right = n;
  39. break;
  40. }
  41. }
  42. }
  43. }
  44. }
  45. // 中序遍历
  46. function inOrder(node) {
  47. if(!(node == null)) {
  48. inOrder(node.left);
  49. console.log(node.show());
  50. inOrder(node.right);
  51. }
  52. }
  53.  
  54. // 先序遍历
  55. function preOrder(node) {
  56. if(!(node == null)) {
  57. console.log(node.show());
  58. preOrder(node.left);
  59. preOrder(node.right);
  60. }
  61. }
  62.  
  63. // 后序遍历
  64. function postOrder(node) {
  65. if(!(node == null)) {
  66. postOrder(node.left);
  67. postOrder(node.right);
  68. console.log("后序遍历"+node.show());
  69. }
  70. }
  71.  
  72. // 二叉树查找最小值
  73. function getMin(){
  74. var current = this.root;
  75. while(!(current.left == null)) {
  76. current = current.left;
  77. }
  78. return current.data;
  79. }
  80.  
  81. // 二叉树上查找最大值
  82. function getMax() {
  83. var current = this.root;
  84. while(!(current.right == null)) {
  85. current = current.right;
  86. }
  87. return current.data;
  88. }
  89. HTML初始化如下:
  90. var nums = new BST();
  91. nums.insert(23);
  92. nums.insert(45);
  93. nums.insert(16);
  94. nums.insert(37);
  95. nums.insert(3);
  96. nums.insert(99);
  97. nums.insert(22);
  98. var min = nums.getMin();
  99. console.log(min);
  100.  
  101. var max = nums.getMax();
  102. console.log(max);

分析还是和上面最小值分析一个道理,这里就不分析了。

上面2个方法返回最小值和最大值,但是有时候,我们希望方法返回存储最小值和最大值的节点,这很好实现,只需要修改方法,让它返回当前节点,而不是节点中存储的数据即可。

在二叉树上查找给定值

在二叉树上查找给定值,需要比较该值和当前节点上的值得大小。通过比较,就能确定如果给定值不在当前节点时,就要向左遍历和向右遍历了。

代码如下:

  1. // 查找给定值
  2. function find(data) {
  3. var current = this.root;
  4. while(current != null) {
  5. if(current.data == data) {
  6. return current;
  7. }else if(data < current.data) {
  8. current = current.left;
  9. }else {
  10. current = current.right;
  11. }
  12. }
  13. return null;
  14. }

代码分析如下:

比如现在的二叉树是如下这个样子:

页面初始化 查找二叉树上的45 节点,代码初始化如下:

var value = nums.find("45");

截图如下:

然后就return 45的节点上了。

所有的JS代码如下:

  1. function Node(data,left,right) {
  2. this.data = data;
  3. this.left = left;
  4. this.right = right;
  5. this.show = show;
  6. }
  7.  
  8. function show() {
  9. return this.data;
  10. }
  11.  
  12. function BST() {
  13. this.root = null;
  14. this.insert = insert;
  15. this.inOrder = inOrder;
  16. this.getMin = getMin;
  17. this.getMax = getMax;
  18. this.find = find;
  19. }
  20.  
  21. function insert(data) {
  22. var n = new Node(data,null,null);
  23. if(this.root == null) {
  24. this.root = n;
  25. }else {
  26. var current = this.root;
  27. var parent;
  28. while(current) {
  29. parent = current;
  30. if(data < current.data) {
  31. current = current.left;
  32. if(current == null) {
  33. parent.left = n;
  34. break;
  35. }
  36. }else {
  37. current = current.right;
  38. if(current == null) {
  39. parent.right = n;
  40. break;
  41. }
  42. }
  43. }
  44. }
  45. }
  46. // 中序遍历
  47. function inOrder(node) {
  48. if(!(node == null)) {
  49. inOrder(node.left);
  50. console.log(node.show());
  51. inOrder(node.right);
  52. }
  53. }
  54.  
  55. // 先序遍历
  56. function preOrder(node) {
  57. if(!(node == null)) {
  58. console.log(node.show());
  59. preOrder(node.left);
  60. preOrder(node.right);
  61. }
  62. }
  63.  
  64. // 后序遍历
  65. function postOrder(node) {
  66. if(!(node == null)) {
  67. postOrder(node.left);
  68. postOrder(node.right);
  69. console.log("后序遍历"+node.show());
  70. }
  71. }
  72.  
  73. // 二叉树查找最小值
  74. function getMin(){
  75. var current = this.root;
  76. while(!(current.left == null)) {
  77. current = current.left;
  78. }
  79. return current.data;
  80. }
  81.  
  82. // 二叉树上查找最大值
  83. function getMax() {
  84. var current = this.root;
  85. while(!(current.right == null)) {
  86. current = current.right;
  87. }
  88. return current.data;
  89. }
  90.  
  91. // 查找给定值
  92. function find(data) {
  93. var current = this.root;
  94. while(current != null) {
  95. if(current.data == data) {
  96. return current;
  97. }else if(data < current.data) {
  98. current = current.left;
  99. }else {
  100. current = current.right;
  101. }
  102. }
  103. return null;
  104. }

从二叉查找树上删除节点。

原理:从二叉树上删除节点首先要判断当前节点是否包含待删除的数据,如果包含,则删除该节点;如果不包含,则要比较当前节点上的数据和待删除的数据。如果待删除数据小于当前节点上的数据,则要移到当前节点的左子节点继续比较;如果删除的数据大于当前节点上的数据,则移至当前节点的右子节点继续比较。

如果待删除节点是叶子节点(没有子节点的节点),那么只需要将父节点指向它的链接指向null;

如果待删除的节点只包含一个子节点,那么原本指向它的节点就得做点调整,使其指向它的子节点。

最后,如果待删除节点包含2个子节点,正确的做法有2种,1:要么查找待删除节点左子树上的最大值,要么查找其右子树上的最小值。这里我们选择后一种;

下面是我们删除节点的JS代码如下:

  1. function remove(data) {
  2. root = removeNode(this.root,data);
  3. }
  4. function getSmallest(node) {
  5. if (node.left == null) {
  6. return node;
  7. }
  8. else {
  9. return getSmallest(node.left);
  10. }
  11. }
  12. function removeNode(node,data) {
  13. if(node == null) {
  14. return null;
  15. }
  16. if(data == node.data) {
  17. // 没有子节点的节点
  18. if(node.left == null && node.right == null) {
  19. return null;
  20. }
  21. // 没有左子节点的节点
  22. if(node.left == null) {
  23. return node.right;
  24. }
  25. // 没有右子节点的节点
  26. if(node.right == null) {
  27. return node.left;
  28. }
  29. // 有2个子节点的节点
  30. var tempNode = getSmallest(node.right);
  31. node.data = tempNode.data;
  32. node.right = removeNode(node.right,tempNode.data);
  33. return node;
  34. }else if(data < node.data) {
  35. node.left = removeNode(node.left,data);
  36. return node;
  37. }else {
  38. node.right = removeNode(node.right,data);
  39. return node;
  40. }
  41. }

我们还是以上面的二叉树来分析下代码原理:

1. 比如我现在要删除根节点为23的节点,代码初始化如下:

nums.remove(23);

执行这个代码后 var tempNode = getSmallest(node.right); 就指向45的那个节点了,如下:

然后执行下面的获取右子树上的最小值的方法;

  1. function getSmallest(node) {
  2. if (node.left == null) {
  3. return node;
  4. }
  5. else {
  6. return getSmallest(node.left);
  7. }
  8. }

里面使用递归的方式执行代码,当node.left == null 时候,就返回当前node节点;如下:

如上所示,当node等于37的时候 就返回node为37的节点。

下面继续执行第二句代码;如下:

node.data = tempNode.data; 那么node.data = 37了;下面是node节点的截图如下:

接着继续执行下面的代码

node.right = removeNode(node.right,tempNode.data);

同时又使用递归的方式removeNode()方法;返回如下节点:

所有的JS代码如下:

  1. function Node(data,left,right) {
  2. this.data = data;
  3. this.left = left;
  4. this.right = right;
  5. this.show = show;
  6. }
  7.  
  8. function show() {
  9. return this.data;
  10. }
  11.  
  12. function BST() {
  13. this.root = null;
  14. this.insert = insert;
  15. this.inOrder = inOrder;
  16. this.getMin = getMin;
  17. this.getMax = getMax;
  18. this.find = find;
  19. this.remove = remove;
  20. }
  21.  
  22. function insert(data) {
  23. var n = new Node(data,null,null);
  24. if(this.root == null) {
  25. this.root = n;
  26. }else {
  27. var current = this.root;
  28. var parent;
  29. while(current) {
  30. parent = current;
  31. if(data < current.data) {
  32. current = current.left;
  33. if(current == null) {
  34. parent.left = n;
  35. break;
  36. }
  37. }else {
  38. current = current.right;
  39. if(current == null) {
  40. parent.right = n;
  41. break;
  42. }
  43. }
  44. }
  45. }
  46. }
  47. // 中序遍历
  48. function inOrder(node) {
  49. if(!(node == null)) {
  50. inOrder(node.left);
  51. console.log(node.show());
  52. inOrder(node.right);
  53. }
  54. }
  55.  
  56. // 先序遍历
  57. function preOrder(node) {
  58. if(!(node == null)) {
  59. console.log(node.show());
  60. preOrder(node.left);
  61. preOrder(node.right);
  62. }
  63. }
  64.  
  65. // 后序遍历
  66. function postOrder(node) {
  67. if(!(node == null)) {
  68. postOrder(node.left);
  69. postOrder(node.right);
  70. console.log("后序遍历"+node.show());
  71. }
  72. }
  73.  
  74. // 二叉树查找最小值
  75. function getMin(){
  76. var current = this.root;
  77. while(!(current.left == null)) {
  78. current = current.left;
  79. }
  80. return current.data;
  81. }
  82.  
  83. // 二叉树上查找最大值
  84. function getMax() {
  85. var current = this.root;
  86. while(!(current.right == null)) {
  87. current = current.right;
  88. }
  89. return current.data;
  90. }
  91.  
  92. // 查找给定值
  93. function find(data) {
  94. var current = this.root;
  95. while(current != null) {
  96. if(current.data == data) {
  97. return current;
  98. }else if(data < current.data) {
  99. current = current.left;
  100. }else {
  101. current = current.right;
  102. }
  103. }
  104. return null;
  105. }
  106.  
  107. function remove(data) {
  108. root = removeNode(this.root,data);
  109. }
  110. function getSmallest(node) {
  111. if (node.left == null) {
  112. return node;
  113. }
  114. else {
  115. return getSmallest(node.left);
  116. }
  117. }
  118. function removeNode(node,data) {
  119. if(node == null) {
  120. return null;
  121. }
  122. if(data == node.data) {
  123. // 没有子节点的节点
  124. if(node.left == null && node.right == null) {
  125. return null;
  126. }
  127. // 没有左子节点的节点
  128. if(node.left == null) {
  129. return node.right;
  130. }
  131. // 没有右子节点的节点
  132. if(node.right == null) {
  133. return node.left;
  134. }
  135. // 有2个子节点的节点
  136. var tempNode = getSmallest(node.right);
  137. node.data = tempNode.data;
  138. node.right = removeNode(node.right,tempNode.data);
  139. return node;
  140. }else if(data < node.data) {
  141. node.left = removeNode(node.left,data);
  142. return node;
  143. }else {
  144. node.right = removeNode(node.right,data);
  145. return node;
  146. }
  147. }
  148. 代码初始化如下:
  149. var nums = new BST();
  150. nums.insert(23);
  151. nums.insert(45);
  152. nums.insert(16);
  153. nums.insert(37);
  154. nums.insert(3);
  155. nums.insert(99);
  156. nums.insert(22);
  157. var min = nums.getMin();
  158. console.log(min);
  159. var max = nums.getMax();
  160. console.log(max);
  161. var value = nums.find("45");
  162. console.log(value);
  163. nums.remove(23);

javascript数据结构与算法-- 二叉树的更多相关文章

  1. javascript数据结构与算法---二叉树(删除节点)

    javascript数据结构与算法---二叉树(删除节点) function Node(data,left,right) { this.data = data; this.left = left; t ...

  2. javascript数据结构与算法---二叉树(查找最小值、最大值、给定值)

    javascript数据结构与算法---二叉树(查找最小值.最大值.给定值) function Node(data,left,right) { this.data = data; this.left ...

  3. javascript数据结构与算法--二叉树遍历(后序)

    javascript数据结构与算法--二叉树遍历(后序) 后序遍历先访问叶子节点,从左子树到右子树,再到根节点. /* *二叉树中,相对较小的值保存在左节点上,较大的值保存在右节点中 * * * */ ...

  4. javascript数据结构与算法--二叉树遍历(先序)

    javascript数据结构与算法--二叉树遍历(先序) 先序遍历先访问根节点, 然后以同样方式访问左子树和右子树 代码如下: /* *二叉树中,相对较小的值保存在左节点上,较大的值保存在右节点中 * ...

  5. javascript数据结构与算法--二叉树遍历(中序)

    javascript数据结构与算法--二叉树遍历(中序) 中序遍历按照节点上的键值,以升序访问BST上的所有节点 代码如下: /* *二叉树中,相对较小的值保存在左节点上,较大的值保存在右节点中 * ...

  6. javascript数据结构与算法--二叉树(插入节点、生成二叉树)

    javascript数据结构与算法-- 插入节点.生成二叉树 二叉树中,相对较小的值保存在左节点上,较大的值保存在右节点中 /* *二叉树中,相对较小的值保存在左节点上,较大的值保存在右节点中 * * ...

  7. javascript数据结构与算法--散列

    一:javascript数据结构与算法--散列  一:什么是哈希表? 哈希表也叫散列表,是根据关键码值(key,value)而直接进行访问的数据结构,它是通过键码值映射到表中一个位置来访问记录的,散列 ...

  8. 为什么我要放弃javaScript数据结构与算法(第八章)—— 树

    之前介绍了一些顺序数据结构,介绍的第一个非顺序数据结构是散列表.本章才会学习另一种非顺序数据结构--树,它对于存储需要快速寻找的数据非常有用. 本章内容 树的相关术语 创建树数据结构 树的遍历 添加和 ...

  9. JavaScript 数据结构与算法之美 - 线性表(数组、栈、队列、链表)

    前言 基础知识就像是一座大楼的地基,它决定了我们的技术高度. 我们应该多掌握一些可移值的技术或者再过十几年应该都不会过时的技术,数据结构与算法就是其中之一. 栈.队列.链表.堆 是数据结构与算法中的基 ...

随机推荐

  1. python爬虫学习(4) —— 手刃「URP教务系统」

    0. 本爬虫目标 模拟登陆URP教务系统 查询 本学期/历年 成绩 计算历年成绩的绩点 下面是一点废「私」话「货」: 一般情况,查询成绩大家会通过如下方式: 登陆信息门户 -> 转到教学空间 - ...

  2. 基于移动端Reactive Native轮播组件的应用与开发详解

    总结下这段时间学习reactive native的一些东西,我们来认识一下,被炒得这么火的rn,究竟是个什么东西,以及如何去搭建自己的demo. reactive  native是什么 由facebo ...

  3. [转载]彻底弄清struct和typedef struct

    struct和typedef struct 分三块来讲述: 1 首先://注意在C和C++里不同 在C中定义一个结构体类型要用typedef: typedef struct Student { int ...

  4. BZOJ 2115 【Wc2011】 Xor

    Description Input 第一行包含两个整数N和 M, 表示该无向图中点的数目与边的数目. 接下来M 行描述 M 条边,每行三个整数Si,Ti ,Di,表示 Si 与Ti之间存在 一条权值为 ...

  5. Android 自定义Dialog类,并在Activity中实现按钮监听。

      实际开发中,经常会用到Dialog,比如退出时候会弹出是否退出,或者还有一些编辑框也会用Dialog实现,效果图如下: 开发中遇到的问题无非在于如果在Activity中监听这个Dialog中实现的 ...

  6. [Leetcode] Course Schedule

    There are a total of n courses you have to take, labeled from 0 to n - 1. Some courses may have prer ...

  7. 树莓派Odroid等卡片式电脑上搭建NAS教程系列6-miniDLNA

    目录: 1. 树莓派Odroid等卡片式电脑上搭建NAS教程系列1-Ubuntu系统安装 2. 树莓派Odroid等卡片式电脑上搭建NAS教程系列2-SSH连接访问 3. 树莓派Odroid等卡片式电 ...

  8. HTML5 移动浏览器支持

  9. mac下需要安装旧 Java SE 6 才能打开程序解决办法

    今天我在mac系统下面安装myeclipse2014(myeclipse-pro-2014-GA-offline-installer-macosx.dmg)的时候,发现显示错误: 您需要安装旧 Jav ...

  10. linux red hat 给普通用户开启root权限

    环境:虚拟机:red hat 6.5:root角色用户:普通用户:宏基笔记本:win7: 操作过程: 1.登录普通用户,进入图形界面(可以设置为启动登录进入命令行界面): 2.按Crl+ALT+F2进 ...