52 # 二叉树的前中后遍历

简介: 52 # 二叉树的前中后遍历

二叉树的遍历

线性数据结构遍历比较简单,可以采用正序遍历、逆序遍历。

遍历树的目的一般是修改树,比如修改树的节点,采用访问者模式

前序遍历

前序遍历(preorder traversal):先访问根节点,前序遍历左子树,前序遍历右子树;遍历 dom 树可以使用

perorderTraversal(visitor) {
    if (visitor == null) return;
    const traversal = (node) => {
        if (node === null) return;
        visitor.visit(node);
        traversal(node.left);
        traversal(node.right);
    };
    traversal(this.root);
}

中序遍历

中序遍历(inorder traversal):中序遍历左子树,根节点,中序遍历右子树;可以顺序打印数据

inorderTraversal(visitor) {
    if (visitor == null) return;
    const traversal = (node) => {
        if (node === null) return;
        traversal(node.left);
        visitor.visit(node);
        traversal(node.right);
    };
    traversal(this.root);
}

后序遍历

后序遍历(postorder traversal):后序遍历左子树,后续遍历右子树,根节点;遍历子节点可使用后序遍历

postorderTraversal(visitor) {
    if (visitor == null) return;
    const traversal = (node) => {
        if (node === null) return;
        traversal(node.left);
        traversal(node.right);
        visitor.visit(node);
    };
    traversal(this.root);
}

层序遍历

层序遍历(level order traversal):从上到下,从左到右依次访问每一个节点

完整代码

实现如下:

// 节点
class Node {
    constructor(element, parent) {
        this.element = element; // 存的数据
        this.parent = parent; // 父节点
        this.left = null; // 左子树
        this.right = null; // 右子树
    }
}
class BST {
    constructor(compare) {
        this.root = null;
        this.size = 0; // 节点个数
        this.compare = compare || this.compare;
    }
    compare(e1, e2) {
        return e1 - e2;
    }
    // 添加节点
    add(element) {
        // 如果根元素不存在
        if (this.root === null) {
            this.root = new Node(element, null);
            this.size++;
            return;
        } else {
            // 如果根元素存在,那么增加的就不是根节点,需要找到 parent
            let currentNode = this.root;
            // 当前比较的结果
            let compare = 0;
            // 先找到需要对比的 parent(当前父节点)
            let parent = null;
            while (currentNode) {
                parent = currentNode;
                compare = this.compare(element, currentNode.element);
                // 如果大于 0 找右树,小于 0 找左树
                if (compare > 0) {
                    currentNode = currentNode.right;
                } else if (compare < 0) {
                    currentNode = currentNode.left;
                } else {
                    // 如果比较后结果一样,由自己决定是否需要覆盖
                    currentNode.element = element; // 覆盖
                    return;
                }
            }
            // 找到了 parent,生成新节点
            let newNode = new Node(element, parent);
            if (compare > 0) {
                parent.right = newNode;
            } else {
                parent.left = newNode;
            }
        }
    }
    // 先序遍历
    perorderTraversal(visitor) {
        if (visitor == null) return;
        const traversal = (node) => {
            if (node === null) return;
            visitor.visit(node);
            traversal(node.left);
            traversal(node.right);
        };
        traversal(this.root);
    }
    // 中序遍历
    inorderTraversal(visitor) {
        if (visitor == null) return;
        const traversal = (node) => {
            if (node === null) return;
            traversal(node.left);
            visitor.visit(node);
            traversal(node.right);
        };
        traversal(this.root);
    }
    // 后序遍历
    postorderTraversal(visitor) {
        if (visitor == null) return;
        const traversal = (node) => {
            if (node === null) return;
            traversal(node.left);
            traversal(node.right);
            visitor.visit(node);
        };
        traversal(this.root);
    }
}
let bst = new BST();
let arr = [10, 8, 19, 6, 15, 22, 20];
arr.forEach((element) => {
    bst.add(element);
});
// 遍历树的目的一般是修改树,比如修改树的节点,采用访问者模式
console.log(
    bst.perorderTraversal({
        visit(node) {
            console.log("visitor.visit---->", node.element);
        },
    })
);
console.log(
    bst.inorderTraversal({
        visit(node) {
            console.log("visitor.visit---->", node.element);
        },
    })
);
console.log(
    bst.postorderTraversal({
        visit(node) {
            console.log("visitor.visit---->", node.element);
        },
    })
);
目录
相关文章
|
1月前
|
索引
【力扣刷题】删除链表的倒数第 N 个结点、两两交换链表中的节点、随机链表的复制
【力扣刷题】删除链表的倒数第 N 个结点、两两交换链表中的节点、随机链表的复制
21 0
|
1月前
|
存储
数据结构:图文详解单链表的各种操作(头插法,尾插法,任意位置插入,删除节点,查询节点,求链表的长度,清空链表)
数据结构:图文详解单链表的各种操作(头插法,尾插法,任意位置插入,删除节点,查询节点,求链表的长度,清空链表)
358 0
|
6月前
数据结构单链表之删除给定位置的链表节点 | 第五套
数据结构单链表之删除给定位置的链表节点 | 第五套
48 0
|
9月前
|
存储 算法
二叉树的创建和遍历
二叉树(Binary tree)是树形结构的一个重要类型。许多实际问题抽象出来的数据结构往往是二叉树形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要。二叉树特点是每个节点最多只能有两棵子树,且有左右之分
73 0
|
存储 编译器
二叉树的递归遍历与迭代遍历(图示)
本文将讲述二叉树递归与迭代的相关知识。
95 0
|
存储 机器学习/深度学习 缓存
链表和有序二叉树插入元素时真的比数组快吗?
公司有位C++标准委员会的顾问大佬,一年会有几次视频讲座,分享一些编程要点或者经验。很多时候都是C++很基础的方面,但是他的讲解视频真的很深入浅出,有时候会“打破”一些理所应当的观点,这篇文章就是让我觉得很有趣,并且意想不到的地方,在这里分享一下。
链表和有序二叉树插入元素时真的比数组快吗?
|
机器学习/深度学习 C++ 容器
二叉树创建和遍历(C++实现)
树(Tree)是n(n≥0)个节点的有限集。在任意一棵树中有且仅有一个特定的称为根(Root)的节点;当n>1时,其余节点可分m(m>0)为个互不相交的有限集T1,T2,...,Tm;其中每一个集合本身又是一棵树,并且称为根的子树(SubTree)。 二叉树(Binary Tree)是一种特殊的有序树型结构,所有节点最多只有2棵子树。
498 0
二叉树的三种遍历方式
二叉树的三种遍历方式
202 0
二叉树的三种遍历方式
二叉查找树的建立,删除,非递归和递归查找给定元素,非递归和递归查找最大元素结点和最小元素结点
二叉查找树的建立,删除,非递归和递归查找给定元素,非递归和递归查找最大元素结点和最小元素结点