顺序存储二叉树线索化二叉树

news2024/11/24 17:29:35

顺序存储二叉树&线索化二叉树

文章目录

  • 顺序存储二叉树&线索化二叉树
    • 顺序存储二叉树
      • 介绍
      • 代码实现
    • 线索化二叉树
      • 介绍
      • 代码实现

顺序存储二叉树

介绍

背景:从数据存储来看,数组存储方式和树的存储方式可以相互转换,即数组可以转换成树,树也可以转换成数组,看下面的示意图。

在这里插入图片描述

特点:

1.顺序二叉树通常只考虑完全二叉树
2.第n个元素的左子节点为 2 * n + 1
3.第n个元素的右子节点为 2 * n + 2
4.第n个元素的父节点为 (n-1) / 2
5.n : 表示二叉树中的第几个元素(按0开始编号如图所示)

在这里插入图片描述

代码实现

package com.datestructures.tree;

public class ArrBinaryTree {
    //数组存储二叉树
    private int[] arr;

    public ArrBinaryTree(int[] arr) {
        this.arr = arr;
    }

    public void preOrder() {
        this.preOrder(0);
    }

    /**
     * 用来以树的形式遍历数组  前序遍历
     *
     * @param index
     */
    private void preOrder(int index) {
        //先判断是否为空
        if (arr == null || arr.length == 0) {
            System.out.println("数组为空,不能遍历顺序二叉树");
            return;
        }
        System.out.print(arr[index]+" ");
        if ((2 * index + 1) < arr.length) {//向左递归
            preOrder(2 * index + 1);
        }
        if ((2 * index + 2) < arr.length) {//向右递归
            preOrder(2 * index + 2);
        }
    }

    public void infixOrder() {
        this.infixOrder(0);
    }

    /**
     * 用来以树的形式遍历数组  中序遍历
     *
     * @param index
     */
    private void infixOrder(int index) {
        //先判断是否为空
        if (arr == null || arr.length == 0) {
            System.out.println("数组为空,不能遍历顺序二叉树");
            return;
        }
        if ((2 * index + 1) < arr.length) {//向左递归
            infixOrder(2 * index + 1);
        }
        System.out.print(arr[index]+" ");
        if ((2 * index + 2) < arr.length) {//向右递归
            infixOrder(2 * index + 2);
        }

    }

    public void postOrder() {
        this.postOrder(0);
    }

    /**
     * 用来以树的形式遍历数组  后序遍历
     * @param index
     */
    private void postOrder(int index){
        //先判断是否为空
        if (arr == null || arr.length == 0) {
            System.out.println("数组为空,不能遍历顺序二叉树");
            return;
        }
        if ((2 * index + 1) < arr.length) {//向左递归
            postOrder(2 * index + 1);
        }
        if ((2 * index + 2) < arr.length) {//向右递归
            postOrder(2 * index + 2);
        }
        System.out.print(arr[index]+" ");
    }
}

测试类

package com.datestructures.tree;

public class ArrBinaryTreeDemo {
    public static void main(String[] args) {
        int[] arr = {1,2,3,4,5,6,7};
        ArrBinaryTree arrBinaryTree = new ArrBinaryTree(arr);
        System.out.println("前序遍历");
        arrBinaryTree.preOrder();
        System.out.println();
        System.out.println("中序遍历");
        arrBinaryTree.infixOrder();
        System.out.println();
        System.out.println("后序遍历");
        arrBinaryTree.postOrder();
    }
}

线索化二叉树

介绍

概念:遍历二叉树是以一定规则将二叉树中的结点排列成一个线性序列,得到二叉树中结点的先序序列、中序序列或后序序列。这实质上是对一个非线性结构进行线性化操作。使每个结点(除第一个和最后一个外)在这些线性序列中有且仅有一个直接前驱和直接后继。

介绍:

1.n个结点的二叉链表中含有n+1(公式 2n-(n-1)=n+1)个空指针域。利用二叉链表中的空指针域,存放指向该结点在某种遍历次序下的前驱和后继结点的指针(这种附加的指针称为"线索")
2.这种加上了线索的二叉链表称为线索链表,相应的二叉树称为线索二叉树(Threaded BinaryTree)。根据线索性质的不同,线索二叉树可分为前序线索二叉树、中序线索二叉树和后序线索二叉树三种
3.一个结点的前一个结点,称为前驱结点
4.一个结点的后一个结点,称为后继结点

应用案例说明:将下面的二叉树,进行中序线索二叉树。中序遍历的数列为 {8, 3, 10, 1, 14, 6}

在这里插入图片描述

思路分析: 中序遍历的结果:{8, 3, 10, 1, 14, 6}

在这里插入图片描述

说明:

当线索化二叉树后,Node节点的 属性 left 和 right ,有如下情况:
1.left 指向的是左子树,也可能是指向的前驱节点. 比如 ① 节点 left 指向的左子树, 而 ⑩ 节点的 left 指向的就是前驱节点.
2.right指向的是右子树,也可能是指向后继节点,比如 ① 节点right 指向的是右子树,而⑩ 节点的right 指向的是后继节点.

代码实现

package com.datestructures.tree;

public class ThreadedBinaryTree {
    private HeroNode root;

    //为了实现线索化  需要创建要给指向当前节点的前驱节点的指针
    //在递归线索化时  pre总是保留前一个节点
    public HeroNode pre = null;//中序线索化前驱节点指针
    public HeroNode pre1 = null;//前序索引化前驱节点指针

    public void setRoot(HeroNode root) {
        this.root = root;
    }

    public void infixthreadedNodes() {
        infixthreadedNodes(root);
    }

    public void prethreadedNodes() {
        prethreadedNodes(root);
    }

    public void postthreadedNodes() {
        postthreadedNodes(root);
    }

    /**
     * 编写对二叉树进行前序线索化的方法
     *
     * @param node 就是当前需要线索化的节点
     */
    public void prethreadedNodes(HeroNode node) {
        //如果node==null 不能线索化
        if (node == null) {
            return;
        }
        //(1)先线索化当前节点
        if (node.getLeft() == null) {
            //让当前节点的左指针指向前驱节点
            node.setLeft(pre1);
            //修改当前节点的左指针类型
            node.setLeftType(1);
        }
        //处理前驱节点的后继节点
        if (pre1 != null && pre1.getRight() == null) {
            //让前驱节点的右指针指向当前节点
            pre1.setRight(node);
            //修改前驱节点的右指针类型
            pre1.setRightType(1);
        }
        //!!! 每处理一个节点后让当前节点是下一个节点的前驱
        pre1 = node;
        //(2)线索化左子树
        if (node.getLeftType() == 0) {
            prethreadedNodes(node.getLeft());
        }
        //(3)线索化右子树
        if (node.getRightType() == 0) {
            prethreadedNodes(node.getRight());
        }
    }

    /**
     * 遍历前序线索化二叉树
     */
    public void prethreadedList() {
        //定义一个变量  存储当前遍历节点  从root开始
        HeroNode node = root;//1  3  8  10  6  14
        while (node != null) {
            //先输出当前节点
            System.out.println(node);
            if (node.getLeftType() == 0) {
                node = node.getLeft();
            } else {
                node = node.getRight();
            }
        }
    }

    /**
     * 编写对二叉树进行中序线索化的方法
     *
     * @param node 就是当前需要线索化的节点
     */
    public void infixthreadedNodes(HeroNode node) {
        //如果node==null 不能线索化
        if (node == null) {
            return;
        }
        //(1)先线索化左子树
        infixthreadedNodes(node.getLeft());
        //(2)线索化当前节点
        if (node.getLeft() == null) {
            //让当前节点的左指针指向前驱节点
            node.setLeft(pre);
            //修改当前节点的左指针类型
            node.setLeftType(1);
        }
        //处理前驱节点的后继节点
        if (pre != null && pre.getRight() == null) {
            //让前驱节点的右指针指向当前节点
            pre.setRight(node);
            //修改前驱节点的右指针类型
            pre.setRightType(1);
        }
        //!!! 每处理一个节点后让当前节点是下一个节点的前驱
        pre = node;
        //(3)线索化右子树
        infixthreadedNodes(node.getRight());

    }

    /**
     * 遍历中序线索化二叉树
     */
    public void infixthreadedList() {
        //定义一个变量  存储当前遍历节点  从root开始
        HeroNode node = root;
        while (node != null) {
            //循环找到leftType==1的,就是中序遍历开始的节点
            while (node.getLeftType() == 0) {
                node = node.getLeft();
            }
            //跳出循环说明找到了开始节点
            System.out.println(node);
            //如果当前节点的右指针指向的是后继节点  则集训输出
            while (node.getRightType() == 1) {
                node = node.getRight();
                System.out.println(node);
            }
            //替换当前节点
            node = node.getRight();
        }
    }

    /**
     * 后序线索化二叉树
     *
     * @param node
     */
    public void postthreadedNodes(HeroNode node) {
        //如果node==null 不能线索化
        if (node == null) {
            return;
        }
        //(1)线索化左子树
        prethreadedNodes(node.getLeft());
        //(2)线索化右子树
        prethreadedNodes(node.getRight());
        //(3)先线索化当前节点
        if (node.getLeft() == null) {
            //让当前节点的左指针指向前驱节点
            node.setLeft(pre1);
            //修改当前节点的左指针类型
            node.setLeftType(1);
        }
        //处理前驱节点的后继节点
        if (pre1 != null && pre1.getRight() == null) {
            //让前驱节点的右指针指向当前节点
            pre1.setRight(node);
            //修改前驱节点的右指针类型
            pre1.setRightType(1);
        }
        //!!! 每处理一个节点后让当前节点是下一个节点的前驱
        pre1 = node;
    }

    /**
     * 遍历后序线索化二叉树
     */
    public void postthreadedList() {
        HeroNode node = root;
        while (node != null) {
            while (node.getLeftType() == 0) {
                node = node.getLeft();
            }
            while (node != null && node.getRightType() == 1) {
                System.out.println(node);
                pre = node;
                node = node.getRight();
            }
            //若node结点为根节点,则遍历完成
            if (node == root) {
                System.out.println(node);
                return;
            }
            //若node.getRight() == pre则说明以node为根结点的子树遍历完成,应遍历node兄弟结点。
            // 先获取node结点的父节点,再获取node结点的兄弟结点。
            //若node结点无兄弟结点,则继续向上寻找。
            while (node != null && node.getRight() == pre) {
                System.out.println(node);
                pre = node;
                //node = node.getParent();
            }
            if (node != null && node.getRightType() == 0) {
                node = node.getRight();
            }
        }
    }
}

节点类

package com.datestructures.tree;


public class HeroNode {
    //节点类
    private int no;
    private String name;
    private HeroNode left;//默认为空
    private HeroNode right;//默认为空
    //以下属性为线索化二叉树要用的属性
    private int leftType;// 0 表示是节点类型  1 表示是线索
    private int rightType;// 0 表示是节点类型  1 表示是线索

    public int getLeftType() {
        return leftType;
    }

    public int getRightType() {
        return rightType;
    }

    public void setLeftType(int leftType) {
        this.leftType = leftType;
    }

    public void setRightType(int rightType) {
        this.rightType = rightType;
    }

//构造器

    public HeroNode(int no, String name) {
        this.no = no;
        this.name = name;
    }

    public int getNo() {
        return no;
    }

    public void setNo(int no) {
        this.no = no;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public HeroNode getLeft() {
        return left;
    }

    public void setLeft(HeroNode left) {
        this.left = left;
    }

    public HeroNode getRight() {
        return right;
    }

    public void setRight(HeroNode right) {
        this.right = right;
    }

    @Override
    public String toString() {
        return "HeroNode{" +
                "no=" + no +
                ", name='" + name + '\'' +
                '}';
    }

    //前序遍历
    public void preOrder() {
        System.out.println(this);//先输出父节点
        //向左递归
        if (this.left != null) {
            this.left.preOrder();
        }
        //向右递归
        if (this.right != null) {
            this.right.preOrder();
        }
    }

    //前序遍历查找
    public HeroNode preOrderSearch(int no) {
        System.out.println("进入前序遍历查找");
        //先判断当前节点是否为目标值
        if (this.no == no) {
            return this;
        }
        //定义一个res来接收结果
        HeroNode resNode = null;
        //如果不是向左递归
        if (this.left != null) {
            resNode = this.left.preOrderSearch(no);
        }
        //如果找到就返回
        if (resNode != null) {
            return resNode;
        }
        //没有找到就向右递归
        if (this.right != null) {
            resNode = this.right.preOrderSearch(no);
        }
        //最后有没有找到都返回
        return resNode;
    }

    //中序遍历
    public void infixOrder() {
        //向左递归
        if (this.left != null) {
            this.left.infixOrder();
        }
        //输出当前节点
        System.out.println(this);
        //向右递归
        if (this.right != null) {
            this.right.infixOrder();
        }
    }

    //中序遍历查找
    public HeroNode infixOrderSearch(int no) {
        //定义一个结果来存放结果
        HeroNode resNode = null;
        //先判断左子节点是否为空
        if (this.left != null) {
            resNode = this.left.infixOrderSearch(no);
        }
        //如果resNode不为空,表明找到 返回即可
        if (resNode != null) {
            return resNode;
        }
        System.out.println("进入中序遍历查找");
        //为空  就和当前节点比较
        if (this.no == no) {
            return this;
        }
        //当前节点不是目标值 则向右查找
        if (this.right != null) {
            resNode = this.right.infixOrderSearch(no);
        }
        //最后返回
        return resNode;
    }

    //后序遍历
    public void postOrder() {
        //向左递归
        if (this.left != null) {
            this.left.postOrder();
        }
        //向右递归
        if (this.right != null) {
            this.right.postOrder();
        }
        //输出当前节点
        System.out.println(this);
    }

    //后序遍历查找
    public HeroNode postOrderSearch(int no) {
        //先定义一个结果
        HeroNode resNode = null;
        //向左递归
        if (this.left != null) {
            resNode = this.left.postOrderSearch(no);
        }
        //如果不为空 说明找到  返回即可
        if (resNode != null) {
            return resNode;
        }
        //否则向右递归
        if (this.right != null) {
            resNode = this.right.postOrderSearch(no);
        }
        //如果不为空 说明找到  返回即可
        if (resNode != null) {
            return resNode;
        }
        System.out.println("进入后序遍历查找");
        //否则和当前节点对比
        if (this.no == no) {
            return this;
        }
        return resNode;
    }
    //删除节点
    public void delNode(int no){
        //因为二叉树是单向的 所以先判断当前节点的子节点是否是要删除的节点,而不是先判断当前节点
        //先判断当前节点的子节点是否为要删除的节点
        if(this.left!=null&&this.left.no==no){
            this.left=null;
            return;
        }
        if(this.right!=null&&this.right.no==no){
            this.right=null;
            return;
        }
        //向左递归 进行删除
        if(this.left!=null){
            this.left.delNode(no);
        }
        //向右递归  进行删除
        if(this.right!=null){
            this.right.delNode(no);
        }
    }
}

测试类

package com.datestructures.tree;

public class ThreadedBinaryTreeDemo {
    public static void main(String[] args) {
        ThreadedBinaryTree threadedBinaryTree =new ThreadedBinaryTree();
        //再创建四个节点
        HeroNode root = new HeroNode(1,"tom");
        HeroNode hero2 = new HeroNode(3,"jack");
        HeroNode hero3 = new HeroNode(6,"smith");
        HeroNode hero4 = new HeroNode(8,"mary");
        HeroNode hero5 = new HeroNode(10,"king");
        HeroNode her06 = new HeroNode(14,"dim");
        //建立联系
        root.setLeft(hero2);
        root.setRight(hero3);
        hero2.setLeft(hero4);
        hero2.setRight(hero5);
        hero3.setLeft(her06);
        threadedBinaryTree.setRoot(root);
        //中序线索化二叉树
        /*threadedBinaryTree.infixthreadedNodes();
        System.out.println("中序线索化");
        System.out.println(hero5.getLeft());
        System.out.println(hero5.getRight());*/
        //遍历中序线索化二叉树
        /*System.out.println("中序遍历");
        threadedBinaryTree.infixthreadedList();*/
        //前序线索化二叉树
        /*threadedBinaryTree.prethreadedNodes();
        System.out.println("前序线索化");
        System.out.println(hero5.getLeft());
        System.out.println(hero5.getRight());
        System.out.println("前序遍历");
        threadedBinaryTree.prethreadedList();*/
        //后序线索化二叉树
        threadedBinaryTree.postthreadedNodes();
        System.out.println(hero5.getLeft());
        System.out.println(hero5.getRight());
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/490666.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

我把大厂起诉了,协商拿了2N,整理点经验心得给大家,关于离职时如何让自己利益最大化!...

离职时&#xff0c;如何让自己的利益最大化&#xff1f; 一位跟大厂仲裁&#xff0c;并通过协商拿到2n的网友分享了自己的经验心得&#xff0c;干货满满&#xff0c;下面是要点总结&#xff1a; 1.大部分裁员都是违法裁员&#xff0c;应该给2n&#xff0c;但公司不会承认&#…

排序算法 — 归并排序

文章目录 归并排序介绍从下往上的归并排序从上往下的归并排序 归并排序实现从上往下的归并排序从下往上的归并排序 归并排序的时间复杂度和稳定性归并排序时间复杂度归并排序稳定性 代码实现核心&总结 每日一道算法&#xff0c;提高脑力。第五天(时隔7天&#xff0c;终于回…

mac下用git客户端生成ssh秘钥并配置到souretree进行使用

一、使用git 生成 ssh 密钥 1、Mac 安装 git 客户端 打开终端&#xff0c;执行命令&#xff1a; $ brew install git2、执行命令 $ git config --global user.name "xxx" 你自己的名字 $ git config --global user.email "xxxxxx.com&q…

Educational-Codeforces-Round-147-Rated-for-Div-2

title: Educational Codeforces Round 147 (Rated for Div. 2) date: 2023-04-21 15:47:29 categories: AlgorithmCodeforces tags:codeforcesdiv2 Educational Codeforces Round 147 (Rated for Div. 2) A. Matching 题目大意 给你一个字符串&#xff0c;里面包含数字和?,…

Redis缓存穿透和雪崩

Redis缓存穿透和雪崩 Redis缓存的使用&#xff0c;极大的提升了应用程序的性能和效率&#xff0c;特别是数据查询方面。但同时&#xff0c;它也带来了一些问题。其中&#xff0c;最要害的问题&#xff0c;就是数据的一致性问题&#xff0c;从严格意义上讲&#xff0c;这个问题…

AI 工具合辑盘点(七)持续更新 之 AI 音频生成工具

AI 音频生成工具 想要不亲自录制&#xff0c;快速将文本转换为语音&#xff1f;AI 音频生成工具为你提供数千种语音选择&#xff0c;从“普通人”的声音到模仿演员、政治家或电影角色的合成声音&#xff0c;各种声音应有尽有 &#x1f5e3; AI 音频生成工具可用于创建商业用途…

模糊PID模糊控制(清晰化方法梯形图实现)

模糊PID的模糊化请参看下面的博客文章: 博途PLC模糊PID三角隶属度函数指令(含Matlab仿真)_plc 模糊pid_RXXW_Dor的博客-CSDN博客三角隶属度函数FC,我们采用兼容C99标准的函数返回值写法,在FB里调用会更加直观,下面给大家具体讲解代码。常规写法的隶属度函数FC可以参看下…

Python小姿势 - Python中的列表推导式

Python中的列表推导式 Python中的列表推导式是一种很好的创建列表的方式。它允许你将一个操作应用于列表中的每个元素&#xff0c;并将结果放入一个新的列表中。 例如&#xff0c;假设你有一个包含数字的列表&#xff0c;但是你想将每个数字都乘以2&#xff0c;并将结果放入一个…

第三十二章 Unity Mecanim动画系统(上)

在上一章节中&#xff0c;我们介绍了Unity的旧版动画系统&#xff0c;本章节来介绍新版的Mecanim动画系统。新版的Mecanim动画系统实际是对旧版动画系统的升级。新版的Mecanim动画系统仍然是建立在动画片段的基础上的&#xff0c;只不过它给我们提供了一个可视化的窗口来编辑动…

服务攻防-数据库安全-服务应用的安全问题以及测试流程-MysqlHadoop未授权访问RCE-漏洞复现

目录 一、服务应用的安全问题 1、配置不当——未授权访问 2、安全机制——特定安全漏洞 3、安全机制——弱口令爆破攻击 二、服务应用的安全测试思路 1、判断服务是否开放 2、判断服务类型 3、判断利用方式 三、Mysql-未授权访问-CVE-2012-2122 利用 1、漏洞概述 2、…

Detours HOOK

参考文本 如何使用Detours库进行DLL注入&#xff0c;拦截API - 知乎 (zhihu.com) 解决‘nmake‘ 不是内部或外部命令,也不是可运行的程序 或批处理文件。_nmake 不是内部或外部命令,也不是可运行的程序 或批处理文件。_AI浩的博客-CSDN博客 Detours使用方法&#xff0c;简单…

五音不全?手把手教你用自己声音唱任何歌;最详细的Auto-GPT整理;4月AI绘画模型推荐;HayoAI平台简直太酷了 | ShowMeAI日报

&#x1f440;日报&周刊合集 | &#x1f3a1;生产力工具与行业应用大全 | &#x1f9e1; 点赞关注评论拜托啦&#xff01; &#x1f916; 『ChatGPT Code Interpreter Magic』魔法&#xff01;离谱&#xff01;正在怀疑人生… OpenAI 近期面向部分用户发放了 Code Interp…

一起单测引起的项目加载失败惨案 | 京东云技术团队

作者&#xff1a;京东科技 宋慧超 一、前言 最近在开发一个功能模块时&#xff0c;在功能自测阶段&#xff0c;通过使用单测测试功能的完整性&#xff0c;在测试单测联通性使用到静态方法测试时&#xff0c;发现单测报错&#xff0c;通过查阅解决方案发现需要对Javaassist包进…

vue3+webpack4 前端优化首屏时间

项目背景 中小项目&#xff0c;Vue-cli3 vue2 webpack4 目标 缩短白屏时间&#xff0c;用户能够更快的看到我的页面&#xff01; 白屏时间&#xff1a;从打开页面到看到页面&#xff0c;中间白屏停留的时间。 方向 1.减少资源体积&#xff0c;从而缩短请求时间 2.减少资…

企业数字化转型为什么难?低代码平台能为企业带来什么?

企业数字化转型困难原因是多方便的&#xff0c;比如&#xff1a; 遗留系统&#xff1a;许多企业在难以替换或与新技术集成的遗留技术系统上投入了大量资金。 变革阻力&#xff1a;企业越大&#xff0c;参与决策的人就越多&#xff0c;让每个人都接受新工作方式的难度就越大。 …

前端架构师-week4-Node多进程开发入门

目录 学习路径 官方文档 什么是进程 child_process 用法 exec & execFile 用法 spawn 用法以及与exec & execFile的区别 fork用法及父子进程通信机制讲解 child_process同步方法使用教程 学习路径 官方文档 中文版&#xff1a;http://nodejs.cn/api/child_pr…

Flutter 如何将代码显示到界面上

前言 如何优雅的将项目中的代码&#xff0c;亦或是你的demo代码展示到界面上&#xff1f;本文对使用简单、便于维护且通用的解决方案&#xff0c;进行相关的对比和探究 为了节省大家的时间&#xff0c;把最终解决方案的相关接入和用法写在前面 预览代码 快速开始 接入&…

C. Permutation Game(博弈 + 拓扑的思想)

Problem - C - Codeforces 经过漫长的一天&#xff0c; Aice和Bob决定玩一个小游戏。游戏棋盘由n个格子组成&#xff0c;在一条直线上&#xff0c;编号从1到n,每个格子包含一个数字4;,qy在1到n.之间&#xff0c;而且没有两个格子包含相同的数字。 一个棋子被放在其中一个格子里…

nestJS入门cli 创建项目以及集成swagger和mysql

nestJs 1. 简介 介绍 NestJS NestJS 是一个基于 TypeScript 的渐进式 Node.js 框架&#xff0c;它结合了 OOP、FP 和 FRP 的元素&#xff0c;以提供一种现代且可扩展的开发体验。NestJS 建立在 Express.js 之上&#xff0c;但是提供了更加抽象和模块化的方式来编写应用程序。…

蓝牙资讯|苹果与谷歌起草蓝牙定位追踪设备行业规范

苹果与谷歌于当地时间5月2日联合提交了一份行业规范草案&#xff0c;以帮助应对蓝牙定位追踪设备遭滥用的问题。目前已有包括三星在内的追踪设备制造厂商宣布支持该草案。 据了解&#xff0c;苹果与谷歌此次联合提交的行业规范草案将云熙蓝牙定位追踪设备兼容跨iOS以及Android平…