数据结构--二叉树(js版)

本文介绍了二叉树作为非线性数据结构的概念,重点讨论了二叉搜索树(BST)的特点和优势,包括快速的查找、添加和删除操作。解释了BST的Node对象和构造函数,详细描述了插入、中序遍历和不同类型的查找方法,以及删除节点的三种情况。此外,还探讨了将计数功能添加到BST节点以记录数据出现频率的可能性,并提出了将方法添加到BST原型以优化内存使用的思考。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

树是一种非线性的数据结构,以分层的方式存储数据,特别是有序列表。树可以分为几个层次,根节点是第0层。没有任何子节点的节点称为叶子节点。

二叉树是一种特殊的树,二叉树进行查找、添加、删除都非常快。二叉树每个节点的子节点不允许超过两个。相对较小的值保存在左节点中,较大的值保存在右节点中。

  • Node对象既保存数据,也保存和其他节点的连接。
  • BST对象的构造函数将根节点初始化为null,以此创建一空节点。
  • 插入节点的时候先判断根节点是否为null,不为null的时候通过遍历,用一个变量存储当前节点,一层层遍历BST,比较数值,直到查找到正确插入点。因为要把插入点和父节点连接起来,所以要有一个指向“父节点”一个指向“当前节点”。然后通过遍历一步步移动。
  • 中序遍历是通过递归,先访问子左树,再访问根节点,最后访问右子树
//节点类
function Node(dara,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;
}

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;
                }
            }
        }
    }
}

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

BST通常有三种类型的查找

  • 查找最小值
    -因为较小值总在左子节点,所以只需要遍历左子树,直到找到最后一个节点。
  • 查找最大值
    -同理,因为较大值总在右子节点,所以只需要遍历右子树。
  • 查找给定值
    -需要比较该值和当前节点上的值大小,确定该左遍历还是右遍历
//找最小值
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 this.current.data;
}

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

从二叉树删除节点的最复杂的,也是分三种情况

  • 是叶子节点
    -只需要将从父节点指向他的链接指向null。
  • 只包含一个子节点
    -如果只有一个子节点,使父节点的链接指向它的子节点。
  • 包含两个子节点
    -要么查找待删除节点子左子树上的最大值,要么查找其右子树上的最小值。创建一个临时节点,将临时节点上的值复制到待删除节点,再删除临时节点。
//接受待删除数据,调用removeNode()删除它
function remove(data) {
    root = this.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;
        }else if(node.left == null) {
            return node.right;
        }else if(node.right == null) {
            return node.left;
        }else {
            var tempNode = this.getSmallest(node.right);    //创建一个临时节点,等于右子数上的最小值
            node.data = tempNode.data;
            node.right = this.removeNode(node.right,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;
    }
}

function getSmallest(node) {
    var current = node;
    while(current.left !== null) {
        current = current.left;
    }
    return current;
}

BST的一个用途是记录一组数据集中数据出现的次数。

  • 修改Node对象,增加一个记录成绩出现频次的成员。并且插入数据的时候判断一下。
function Node(data,left,right) {
    this.data = data;
    this.left = left;
    this.right = right;
    this.count = 1;
}

//插入数据时如果已经存在就使用updata()
function updata(data) {
    var grade = this.find(data);
    grade.count++;
    return grade;
}

var g = "123";
var bst = new BST();
var aGrade = bst.find(g);
if(aGrade == null) {
    bst.insert(g);
}else {
    bst.updata(g);
}

其实。。。我想了下,感觉那些方法好像可以加到BST的原型上,这样就不会每创建一个BST对象就创建一堆方法,构造函数就不用写一堆this.方法 = 方法。而且这样写把方法定义到全局变量中,使得其他对象也能调用。这样写的方式还是为了附和Java这类语言的吧~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值