树结构的自定义及基本算法(Java数据结构学习笔记)

本文介绍了树这一非线性数据结构的抽象数据类型(ADT)模型,并通过Java语言具体实现了树的节点模型,包括获取节点大小、高度、深度等基本操作。

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

数据结构可以归类两大类型:线性结构与非线性结构,本文的内容关于非线性结构:的基本定义及相关算法。关于树的一些基本概念定义可参考:维基百科
树的ADT模型:
根据树的定义,每个节点的后代均构成一棵树树,称为子树。因此从数据类型来讲,树、子树、树节点是等同地位,可将其看作为一个节点,用通类:Tree表示。如下图所示:
这里写图片描述
图:Tree ADT模型示意图
可采用“父亲-儿子-兄弟”模型来表示树的ADT。如图所示,除数据项外,分别用三个引用表示指向该节点的父亲,儿子,兄弟。
这里写图片描述

图:“父亲-儿子-兄弟”模型的数据结构示意图

表:树ADT实现的操作
这里写图片描述

就对树的更新操作而言,不同的应用问题会要求树结构提供不同方法。这方面的差异太大,无法在树 ADT 中定义出通用的更新操作。在之后将结合各种应用问题,陆续给出一些具体的更新操作的实现。

树的java接口:

package com.tree;

/**
 * Java Structure for Tree
 * Construct interface Tree
 * @author gannyee
 *
 */
public interface Tree {
    //Get size of tree which recent node as parent
    public int getSize();

    //Get height of recent node
    public int getHeight();

    //Get depth of recent node
    public int getDepth();

    //Get element of recent node
    public Object getElement();

    //Set element of recent node, return former element
    public Object setElement(Object newElement);

    //Get parent of recent node
    public TreeLinkedList getParent();

    //Get first child of recent node
    public TreeLinkedList getFirstChild();

    //Get biggest sibling of recent node
    public TreeLinkedList getNextSibling();
}

Java代码:树节点模型实现

package com.tree;

import java.lang.reflect.Constructor;

public class TreeLinkedList implements Tree{
    //Pointer point to parent
    private TreeLinkedList parent;
    //Element
    private Object element;
    //Pointer point to firstChild
    private TreeLinkedList firstChild;
    //Pointer point to nextSibling
    private TreeLinkedList nextSibling;

    //Constructor
    public TreeLinkedList(){
        this(null,null,null,null);
    }

    //Constructor with parameters
    public TreeLinkedList(TreeLinkedList p, Object e,TreeLinkedList f,TreeLinkedList n){
        this.parent = p;
        this.element = e;
        this.firstChild = f;
        this.nextSibling = n;
    }
    //Get size of tree which recent node as parent
    public int getSize(){
        int size = 1; //Recent node also include own children
        TreeLinkedList subTree = firstChild;//Start with first child
        while(null != subTree){
            size += subTree.getSize(); 
            subTree = subTree.getNextSibling();//Get all descendants
        }
        return size;
    }

    //Get height of recent node
    public int getHeight(){
        int height = -1;//Recent node's(parent) height
        TreeLinkedList subTree = firstChild;//Start with first child

        while(null != subTree){
            height = Math.max(height, subTree.getHeight());//Get the max height
            subTree = subTree.getNextSibling();
        }
        return height + 1;//Get recent node height
    }

    //Get depth of recent node
    public int getDepth(){
        int depth = 0;
        TreeLinkedList p = parent;//Start with parent
        while(p != null){
            depth ++;
            p = p.getParent();//Get all parents of every node
        }
        return depth;
    }

    //Get element of recent node,if nothing return null
    public Object getElement(){
        return this.element;
    }

    //Set element of recent node,return former element
    public Object setElement(Object newElement){
        Object swap;
        swap = this.element;
        this.element = newElement;
        return this.element;
    }

    //Get parent of recent node,if nothing return null
    public TreeLinkedList getParent(){
        return parent;
    }

    //Get first child of recent node,if nothing return null
    public TreeLinkedList getFirstChild(){
        return firstChild;
    }

    //Get biggest sibling of recent node,if nothing return null
    public TreeLinkedList getNextSibling(){
        return nextSibling;
    }
}

测试代码:

package com.tree;

public class TreeTest {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub

        TreeLinkedList a = new TreeLinkedList();
        TreeLinkedList b = new TreeLinkedList();
        TreeLinkedList c = new TreeLinkedList();
        TreeLinkedList d = new TreeLinkedList();
        TreeLinkedList e = new TreeLinkedList();
        TreeLinkedList f = new TreeLinkedList();
        TreeLinkedList g = new TreeLinkedList();

        a = new TreeLinkedList(null,0,d,null);
        b = new TreeLinkedList(a,1,d,c.getFirstChild());
        c = new TreeLinkedList(a,2,null,null);
        d = new TreeLinkedList(b,3,f,e.getFirstChild());
        e = new TreeLinkedList(b,4,null,null);
        f = new TreeLinkedList(d,5,null,g.getFirstChild());
        g = new TreeLinkedList(d,6,null,null);

        System.out.println(a.getDepth());
        System.out.println(b.getDepth());
        System.out.println(c.getDepth());
        System.out.println(d.getDepth());
        System.out.println(e.getDepth());
        System.out.println(f.getDepth());

        System.out.println(a.getHeight());
        System.out.println(b.getHeight());
        System.out.println(c.getHeight());
        System.out.println(d.getHeight());
        System.out.println(e.getHeight());
        System.out.println(f.getHeight());
        System.out.println(g.getHeight());

    }

}

测试结果:

0
1
2
com.tree.TreeLinkedList@7c1c8c58
1
null
null

后续将给出关于树的遍历算法!

参考文献:数据结构与算法( Java 描述)邓俊辉 著

$(function(){ $.fn.extend({ SimpleTree:function(options){ //初始化参数 var option = $.extend({ click:function(a){ } },options); option.tree=this; /* 在参数对象中添加对当前菜单树的引用,以便在对象中使用该菜单树 */ option._init=function(){ /* * 初始化菜单展开状态,以及分叉节点的样式 */ this.tree.find("ul ul").hide(); /* 隐藏所有子级菜单 */ this.tree.find("ul ul").prev("li").removeClass("open"); /* 移除所有子级菜单父节点的 open 样式 */ this.tree.find("ul ul[show='true']").show(); /* 显示 show 属性为 true 的子级菜单 */ this.tree.find("ul ul[show='true']").prev("li").addClass("open"); /* 添加 show 属性为 true 的子级菜单父节点的 open 样式 */ }/* option._init() End */ /* 设置所有超链接不响应单击事件 */ this.find("a").click(function(){ $(this).parent("li").click(); return false; }); /* 菜单项 接受单击 */ this.find("li").click(function(){ /* * 当单击菜单项 * 1.触发用户自定义的单击事件,将该 标签中的第一个超链接做为参数传递过去 * 2.修改当前菜单项所属的子菜单的显示状态(如果等于 true 将其设置为 false,否则将其设置为 true) * 3.重新初始化菜单 */ option.click($(this).find("a")[0]); /* 触发单击 */ /* * 如果当前节点下面包含子菜单,并且其 show 属性的值为 true,则修改其 show 属性为 false * 否则修改其 show 属性为 true */ /* if($(this).next("ul").attr("show")=="true"){ $(this).next("ul").attr("show","false"); }else{ $(this).next("ul").attr("show","true"); }*/ /* 初始化菜单 */ option._init(); }); /* 设置所有父节点样式 */ this.find("ul").prev("li").addClass("folder"); /* 设置节点“是否包含子节点”属性 */ this.find("li").find("a").attr("hasChild",false); this.find("ul").prev("li").find("a").attr("hasChild",true); /* 初始化菜单 */ option._init(); }/* SimpleTree Function End */ }); });
/** * 根据等级查询类目树 * * @param level * @return */ @Override public List queryCategoryTree(Integer level) { //查询当前级别下类目 List list = categoryDAO.list(level); //组装好的类目树,返回前端 List categoryTree = new ArrayList(); //所有类目 List allDTOList = new ArrayList(); if (CollectionUtils.isEmpty(list)) { return categoryTree; } for (CategoryDO categoryDO : list) { allDTOList.add(new CategoryTreeDTO().convertDOToDTO(categoryDO)); } //当前等级类目 categoryTree = allDTOList.stream().filter(dto -> level.equals(dto.getLevel())).collect(Collectors.toList()); for (CategoryTreeDTO categoryTreeDTO : categoryTree) { //组装类目为树结构 assembleTree(categoryTreeDTO, allDTOList,Constants.CATEGORY_MAX_LEVEL - level); } return categoryTree; } /** * 组装树 * * @param categoryTreeDTO * @param allList * @param remainRecursionCount 剩余递归次数 * @return */ public CategoryTreeDTO assembleTree(CategoryTreeDTO categoryTreeDTO, List allList, int remainRecursionCount) { remainRecursionCount--; //最大递归次数不超过Constants.CATEGORY_MAX_LEVEL-level次,防止坏数据死循环 if(remainRecursionCount < 0){ return categoryTreeDTO; } String categoryCode = categoryTreeDTO.getCategoryCode(); Integer level = categoryTreeDTO.getLevel(); //到达最后等级树返回 if (Constants.CATEGORY_MAX_LEVEL == level) { return categoryTreeDTO; } //子类目 List child = allList.stream().filter(a -> categoryCode.equals(a.getParentCode())).collect(Collectors.toList()); if (null == child) { return categoryTreeDTO; } categoryTreeDTO.setChildren(child); //组装子类目 for (CategoryTreeDTO dto : child) { assembleTree(dto, allList,remainRecursionCount); } return categoryTreeDTO; }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值