《数据结构与算法JavaScript描述》二叉树和二叉查找树(学习笔记C10)

本文深入探讨了二叉树和二叉查找树的基本概念与特性,包括树的定义、二叉树的特殊性质、二叉查找树的插入、查找、删除操作以及遍历算法。通过具体代码实现,展示了如何构建和操作二叉查找树,适用于初学者理解二叉树结构及其在数据存储和检索中的应用。

二叉树和二叉查找树

相关概念

1.树是一种非线性的数据结构,以分层的方式存储数据。
2.树被用来存储具有层级关系的数据,比如文件系统中的文件;树还被用来存储有序列表。
3.选择树而不是那些基本的数据结构,是因为在二叉树上进行查找非常快(而在链表上查找则不是这样),为二叉树添加或删除元素也非常快(而对数组执行添加或删除操作则不是这样)。
4.二叉树是一种特殊的树,它的子节点个数不超过两个。
5.二叉查找树是一种特殊的二叉树,相对较小的值保存在左节点中,较大的值保存在右节点中。

代码

// 二叉树和二叉查找树

// 1.二叉查找树 BST
function Node(data, left, right) {
    this.data  =data
    this.left = left
    this.right = right
    this.show = show
}

function show() {
    return this.data
}

function BST() {
    this.root = null
    this.insert = insert
    this.inOrder = inOrder
    this.preOrder = preOrder
    this.postOrder = postOrder
    this.getMin = getMin
    this.getMax = getMax
    this.find = find
    this.update = update
}

function insert(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
                }
            }
        }
    }

}

// 2.遍历二叉查找树
/**
 * 先序遍历:先访问根节点,再以同样方式访问左子树和右子树
 * 中序遍历:按照节点上的键值,以升序访问BST上所有节点
 * 后序遍历:先访问叶子节点,从左子树到右子树,再到根节点
 */

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

  // 先序遍历
 function preOrder(node) {
     if (!(node == null)) {
         console.log(node.show() + ' ')
         preOrder(node.left)
         preOrder(node.right)
     }
 }

 // 后序遍历
 function postOrder(node) {
     if (!(node == null)) {
         postOrder(node.left)
         postOrder(node.right)
         console.log(node.show() + ' ')
     }
 }

 // 测试遍历
  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: ");
  inOrder(nums.root);
  console.log("preOrder traversal: ");
  preOrder(nums.root);
  console.log("postOrder traversal: ");
  postOrder(nums.root);
 
 // 3.在二叉查找树上进行查找
 
 // 查找最小值
 function getMin() {
     var current = this.root
     while (!(current.left == null)) {
         current = current.left
     }
     return current.data
 }
 
 // 查找最大值
 function getMax() {
     var current = this.root
     while (!(current.right == null)) {
         current = current.right
     }
     return current.data
 }

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

 // 测试最值/指定值
  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);
  var min = nums.getMin();
  console.log("The minimum value of the BST is: " + min);
  console.log("\n");
  var max = nums.getMax();
  console.log("The maximum value of the BST is: " + max);

  inOrder(nums.root);
  console.log("\n");
  console.log("Enter a value to search for: ");
  var value = parseInt(66);
  var found = nums.find(value);
  if (found != null) {
      console.log("Found " + value + " in the BST.");
  } else {
      console.log(value + " was not found in the BST.");
  }

 // 4.删除指定节点
 function remove(data) {
     root = removeNode(this.root, data)
 }

 function removeNode(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
         }
         // 有两个子节点
         var tempNode = getSmallest(node.right)
         node.data = tempNode.data
         node.right = removeNode(node.right, tempNode.data)
         return node
     } else if (data < node.data) {
         node.left = removeNode(node.left, data)
         return node

     } else {
         node.right = removeNode(node.right, data)
         return node
     }
 }

 // 5.实例:计数
 function Node(data, left, right) {
     this.data = data
     this.count = 1
     this.left = left
     this.right = right
     this.show = show
 }
 // 更新计数
 function update(data) {
     var grade = this.find(data)
     grade.count++
     return grade
 }
 // 
 function prArray(arr) {
     console.log(arr[0].toString() + ' ')
     for(var i = 1; i < arr.length; ++i) {
         console.log(arr[i].toString() + ' ')
         if (i % 10 == 0) {
             console.log('\n')
         }
     }
 }

 function genArray(length) {
     var arr = []
     for(var i = 0; i < length; ++i) {
         arr[i] = Math.floor(Math.random() * 101)
     }
     return arr
 }

 var grades = genArray(100)
 prArray(grades)
 var gradedistro = new BST()
 for(var i = 0; i < grades.length; ++i) {
     var g = grades[i]
     var grade = gradedistro.find(g)
     if (grade == null) {
         gradedistro.insert(g)
     } else {
         gradedistro.update(g)
     }
 }
 var cont = 'y'

 while (cont == 'y') {
     console.log('\n\nEnter a grade: ')
     var g = parseInt(99)
     var aGrade = gradedistro.find(g)
     if (aGrade == null) {
         console.log('No occurrences of ' + g)
     } else {
         console.log('Look at another grade: ')
         cont = 88
     }
 }
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值