树结构列表按父子顺序排序

介绍了一种用于将具有父子关系的节点按父节点优先的原则进行排序的算法实现。该算法适用于节点集合中父节点和子节点顺序随机的情况,确保排序后的列表中每个子节点都位于其父节点之后。

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

package com.naydog;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 目的:传过来的节点集合顺序随机,需要排序以保证父节点在子节点之前
 * 只保证子节点在父节点后面,不保证紧随其后
 * 节点有id,父节点pid字段,以及其他若干字段
 */
public class SortByParentAndChild {

    public static List<E> sortParentAndChild(List<E> entities) {
        // 1. 寻找集合中的所有根节点
        Map<String, List<E>> pMap = new HashMap<String, List<E>>(); // 父节点为key
        Set<String> ids = new HashSet<String>(); // 存储节点id
        Set<String> pids = new HashSet<String>(); //存储父节点id
        for (E entity : entities) {
            ids.add(entity.getId());
            String pid = entity.getPid();
            pids.add(pid);
            if(null == pMap.get(pid)) {
                pMap.put(pid, new ArrayList<E>());
            }
            pMap.get(pid).add(entity);
        }
        pids.removeAll(ids); // 得到根节点

        // [OPTIONAL] 节点id重复,退出
        if (ids.size() < entities.size()) {
            return null;
        }

        // 2. 父子排序
        List<E> sortedList= new ArrayList<E>();
        for (String rootPid : pids) {
            List<E> queue = pMap.remove(rootPid);
            if (null != queue) {
                while(queue.size() > 0) {
                    E entity = queue.remove(0);
                    sortedList.add(entity);
                    List<E> tmpList = pMap.remove(entity.getId());
                    if (null != tmpList) {
                        queue.addAll(tmpList);
                    }
                }
            }
        }
        return sortedList;
    }

    public static void main(String[] args) {
        List<E> list = new ArrayList<E>();
        list.add(new E("A2", "A1"));
        list.add(new E("A1", "0"));
        list.add(new E("A3", "A1"));
        list.add(new E("C1", "1"));
        list.add(new E("B3", "B2"));
        list.add(new E("B2", "B1"));
        list.add(new E("B1", "0"));
        System.out.println(sortParentAndChild(list));
    }
}

/**
 * 节点
 */
class E {
    private String id;
    private String pid;

    public E(String id, String pid) {
        this.id = id;
        this.pid = pid;
    }

    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getPid() {
        return pid;
    }
    public void setPid(String pid) {
        this.pid = pid;
    }

    @Override
    public String toString() {
        return "E [id=" + id + ", pid=" + pid + "]";
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值