评论树数据结构与算法

756 阅读2分钟

    由于本人正在建立个人博客网站,正涉及评论区功能数据结构,评论区的排布越看越像一颗树,所以采纳了树数据结构。

树结构

拆分理解:

拆分理解

每个子树结点也是往下层级的根结点,可结合下方数据结构理解

评论

这里是cnode中文社区部分评论区,有没有发现规律呢?

一条评论(包括顶端评论 [根结点] 及子评论 [子树结点] ) == 一棵树

评论区 == 多条评论 == 多棵树

评论区实际是遍历了多棵树。

代码演示

概念视图

/**
 * 
 *           A           根结点
 *         / \ \ 
 *        B   C  D     以下均为子树结点
 *     / /     \
 *    E F       G
 *              /\
 *             H  I
 * 问题: 按照字母由上至下,由左至右读取数据,模拟评论树数据结构,顺序:A B E F C G N I D
 * 应用场景: 显示评论树
 * 以下结构 中符号是 '|-' 是模拟设置css margin-left  
 * A、B ... 大写英文理解成一条评论中的评论内容: 
 * //程序输出:
 * A  
 * |-B 
 * |-|-E
 * |-|-F
 * |-C
 * |-|-G
 * |-|-|-H
 * |-|-|-I
 * |-D
 * 
 * 脑补评论区
 * 第一条评论,也就是第一课树:
 * A评论内容
 *   B评论A 
 *     E评论B
 *     F评论B
 *   C评论A
 *     G评论C
 *       H评论G
 *       I评论G
 *   D评论A
 *
 * 第二条评论,也就是第二课树:
 * A评论内容
 *   B评论A 
 *     E评论B
 *     F评论B
 *   C评论A
 *     G评论C
 *       H评论G
 *       I评论G
 *   D评论A
 *
 * 思路: 
 * 方案: 先序遍历,递归
 * 先取出根结点数据域,检测是否存在子树结点,存在则遍历,遇到null子结点返回,最后从左子结点树到右全遍历完则退出,从左到右实际是遍历子树结点数组默认左到右
 * 递归边界: 最右最下子树节点为null或空数组
 *  
 */

算法demo

//树数据结构
const dataBase = {
    val: "A", //数据域,根结点
    childNode: [ //子树结点,数组
        {
            val: "B",
            childNode: [
                {
                    val: "E",
                    childNode: [

                    ]
                },
                {
                    val: "F",
                    childNode: [

                    ]
                }
            ]
        },
        {
            val: "C",
            childNode: [
                {
                    val: "G",
                    childNode: [
                        {
                            val: "H",
                            childNode: [

                            ]
                        },
                        {
                            val: "I",
                            childNode: [

                            ]
                        }
                    ]
                },
            ]
        },
        {
            val: "D",
            childNode: []
        },
    ]
}

/**
 * 遍历评论树
 * @param {Objec} root 根结点
 * @param {num} num 打印符号计算符号数,非核心算法
 * 
 */
function preorder(root, num) {
     ///打印用,非核心算法代码,前端可在这里设定父子评论样式//
     let ss = '';
     if(num > 0){
        const newStrArr = new Array(num).fill("|-");
        const strArr = newStrArr.join('')    
        ss = strArr;
     }
     ////////////////////////
    // 读取根结点数据域
    console.log(`${ss}${root.val}`);
    //设定边界,Boolean(root.childNode) === false  
    if (!root.childNode || (root.childNode && root.childNode.length === 0)) return;
    num++;
    //读取子结点树
    for (let i = 0; i < root.childNode.length; i++) {
        const item = root.childNode[i];
        preorder(item, num);
    }

}

function main(root) {
    let num = 0;
    preorder(root, num);
}

main(dataBase);

输出:

  A  
  |-B 
  |-|-E
  |-|-F
  |-C
  |-|-G
  |-|-|-H
  |-|-|-I
  |-D