js实现二叉树、二叉查找树 5年前

树是一种数据结构,该章节讨论二叉树(二叉树的每个节点的子节点不允许超过两个),二叉树中有又分为完全二叉树和不完全二叉树.....

不在本章节赘述相关概念,感兴趣可以去查阅《数据结构》。


你将会获得:

1.如何使用js实现二叉查找树。

2.学会前、中、后序遍历。

3.了解相关实现原理

阅读时长>5min,可选择直接调试代码

特点

二叉查找树中序遍历后,得到的增序的排列方式。

预览

以下封装的二叉查找树,包含了查找方法

function Node(data, left, right) {
  this.data = data;
  this.left = left;
  this.right = right;

}
Node.prototype.show = function() {
  return this.data;
}


function BST() {
  this.root = null;
}
BST.prototype.insert = function (data) {
  var n = new Node(data, null, null);
  if (this.root == null) {
    this.root = n;
  } else {
    var current = this.root;
    var parent;
    while (true) {
      parent = current;
      if (data < current.data) {
        current = current.left;
        if (current == null) {
          parent.left = n;
          break;
        }
      } else {
        current = current.right;
        if (current == null) {
          parent.right = n;
          break;
        }
      }
    }
  }
}

BST.prototype.inOrder = function(node) {
  //  中序遍历
  if (!(node == null)) {
    inOrder(node.left);
    console.log(node.show() + "");
    inOrder(node.right);
  }
}

BST.prototype.preOrder = function(node) {
  //  先序
  if (!(node == null)) {
    console.log(node.show() + "");
    preOrder(node.left);
    preOrder(node.right);
  }
}

BST.prototype.postOrder = function(node) {
  //  先序
  if (!(node == null)) {
    postOrder(node.left);
    postOrder(node.right);
    console.log(node.show() + "");
  }
}

//  查找最小值

BST.prototype.getMin = function() {
  var current = this.root;
  while (current.left !== null) {
    current = current.left;
  }
  return current.data;
}

//  查找最大值

BST.prototype.getMax = function() {
  var current = this.root;
  while (current.right !== null) {
    current = current.right;
  }
  return current.data;
}

//  查找给定值
BST.prototype.find = function(data) {
  var current = this.root;
  while (current != null) {
    if (current.data == data) {
      return current;
    } else if (data < current.data) {
      current = current.left;
    } else if (data > current.data) {
      current = current.right;
    }
  }
  return null;
}



BST.prototype.remove = function(data) {

  this.root = this.removeNode(this.root, data);
  console.log(this.root,1)
}

BST.prototype.removeNode = function(node, data) {
  if (node == null) {
    return null;
  }
  if (data == node.data) { 
    // 没有子节点的节点 
    if (node.left == null && node.right == null) {
      return null;
    } 
    // 没有左子节点的节点 
    if (node.left == null) {
      return node.right;
    } 
    // 没有右子节点的节点 
    if (node.right == null) {
      return node.left;
    } 
    //  查找最小节点
    let getSmallest = function(node) {
      if (node.left === null && node.right == null) {
          return node;
      }
      if (node.left != null) {
          return node.left;
      }
      if (node.right !== null) {
          return getSmallest(node.right);
      }

  }
    // 有两个子节点的节点 
    var tempNode = getSmallest(node.right);
    node.data = tempNode.data;
    node.right = this.removeNode(node.right, tempNode.data);
    return node;
  } else if (data < node.data) {
    node.left = this.removeNode(node.left, data);
    return node;
  } else {
    node.right = this.removeNode(node.right, data);
    return node;
  }
}

中序排列

var nums = new BST(); 
nums.insert(23); 
nums.insert(45); 
nums.insert(16); 
nums.insert(37); 
nums.insert(3); 
nums.insert(99); 
nums.insert(22); 
console.log("Inorder traversal: "); 
nums.inOrder(nums.root);

> Inorder traversal: 
> 3 16 22 23 37 45 99 // 增序

1.实现

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

// 节点
function Node(data, left, right) {
  this.data = data;
  this.left = left;
  this.right = right;
  this.show = show;
}
Node.prototype.show = function() {
  return this.data;
}

1.1创建BST类

BST 先要有一个 insert() 方法,用来向树中加入新节点。

首先要创建一个 Node 对象,将数据传入该对象保存。其次检查 BST 是否有根节点,如果没有,那么这是棵新树,该节点就是根节点,这个方法 到此也就完成了;否则,进入下一步。如果待插入节点不是根节点,那么就需要准备遍历 BST,找到插入的适当位置。该过程类 似于遍历链表。用一个变量存储当前节点,一层层地遍历 BST。进入 BST 以后,下一步就要决定将节点放在哪个地方。找到正确的插入点时,会跳出循 环。查找正确插入点的算法如下。

(1) 设根节点为当前节点。 (2) 如果待插入节点保存的数据小于当前节点,则设新的当前节点为原节点的左节点;反 之,执行第 4 步。 (3) 如果当前节点的左节点为 null,就将新的节点插入这个位置,退出循环;反之,继续 执行下一次循环。 (4) 设新的当前节点为原节点的右节点。 (5) 如果当前节点的右节点为 null,就将新的节点插入这个位置,退出循环;反之,继续 执行下一次循环。

function Node(data, left, right) {
  this.data = data;
  this.left = left;
  this.right = right;

}
Node.prototype.show = function() {
  return this.data;
}


function BST() {
  this.root = null;
}
BST.prototype.insert = function (data) {
  var n = new Node(data, null, null);
  if (this.root == null) {
    this.root = n;
  } else {
    var current = this.root;
    var parent;
    while (true) {
      parent = current;
      if (data < current.data) {
        current = current.left;
        if (current == null) {
          parent.left = n;
          break;
        }
      } else {
        current = current.right;
        if (current == null) {
          parent.right = n;
          break;
        }
      }
    }
  }
}

以上是最主要的,二叉查找树的js实现,其他方法简单描述一下


中序:就是先访问左子节点-->根节点-->右子节点

js实现二叉树、二叉查找树

先序: 就是先访问根节点再访问子节点

js实现二叉树、二叉查找树

后序:最后访问根节点 js实现二叉树、二叉查找树

删除二叉树节点:

删除节点主要分为,叶子节点,有左节点,有右节点,有两个子节点;

思路就是:

  1. 找到要删除节点,判断是否含有子节点。

  2. 如果没有子节点,便将该节点的值置为null。

    2.1 有左/右节点,被删节点指向子节点。

    2.2 含左右节点:

    • (1)查找待删节点的左子树的最大值
    • (2)查找待删节点的右子树的最小值

将待删节点的值替换成以上(1)/(2)的值

以下选的是(2)方案

BST.prototype.remove = function(data) {
  //  最后改变根节点值
  this.root = this.removeNode(this.root, data);
}
//  返回的是node类型
BST.prototype.removeNode = function(node, data) {
  if (node == null) {
    return null;
  }
  if (data == node.data) { 
    // 没有子节点的节点 
    if (node.left == null && node.right == null) {
      return null;
    } 
    // 没有左子节点的节点 
    if (node.left == null) {
      return node.right;
    } 
    // 没有右子节点的节点 
    if (node.right == null) {
      return node.left;
    } 
    //  查找最小节点
    let getSmallest = function(node) {
      if (node.left === null && node.right == null) {
          return node;
      }
      if (node.left != null) {
          return node.left;
      }
      if (node.right !== null) {
          return getSmallest(node.right);
      }

  }
    // 有两个子节点的节点 
    var tempNode = getSmallest(node.right);
    node.data = tempNode.data;
    //  处理待删节点的右子树
    node.right = this.removeNode(node.right, tempNode.data);
    return node;
  } else if (data < node.data) {
    node.left = this.removeNode(node.left, data);
    return node;
  } else {
    node.right = this.removeNode(node.right, data);
    return node;
  }
}

欢迎关注《前端划水笔记》

原文地址 https://mp.weixin.qq.com/s/Qc5_68ljBWjVee6cHrFUTg

image
名字不知道怎么读
泪中有神明。
6
发布数
4
关注者
3201
累计阅读

热门教程文档

Vue
25小节
React
18小节
Spring Boot
24小节
MySQL
34小节
Objective-C
29小节
广告