多树优先级排序算法

时间:2016-04-23 14:28:28

标签: java performance sorting recursion

我想咨询有关订购数据的算法。

问题

我需要根据几个标准对记录列表(POJO)进行排序。

  1. 父子关系(没有继承,只是属性)
  2. 每个树的世代级别内的唯一排序ID(唯一)。
  3. 每条记录都有以下属性:

    • ID - 唯一标识每条记录
    • 家长ID - 标识记录的父级。如果与id相同,则这是顶级根节点
    • 订单号 - 订购同一代/家庭中的儿童。

    示例记录。它们并不总是处于良好的数字顺序;)

    enter image description here
    分类后:
    enter image description here 请注意,由于订单号(优先级),记录14在记录5之前。

    在我的数据集中,大约有3,000条记录,通常不超过3或4级深度。

    策略


    从两个列表开始:
     1.包含要订购的记录的列表  2.一个空列表,用于保存所有已排序的记录

    第1步:遍历记录并获取所有顶级节点(id =父ID),按订单号对其进行排序,然后将其添加到第二个列表中。
    第2步对于列表2中的每个节点,循环遍历列表1并抓取所有子节点,按顺序号对它们进行排序,然后将它们直接插入到父节点之后的列表2中。
    请注意,几乎所有排序都在步骤2中进行。

    这是一个贯穿始终。

    enter image description here

    问题


    我相信第2步将使算法复杂度至少为O(n²) 这种算法的优点和缺点与递归有什么关系?
    是否有更有效的算法可供使用?

2 个答案:

答案 0 :(得分:0)

现在已经晚了,但我想我明白了:)

List<Pojo> list = Arrays.asList(
        new Pojo(1,1,1),new Pojo(2,1,1),
        new Pojo(3,2,1),new Pojo(4,3,1),new Pojo(5,2,3),
        new Pojo(6,5,1),new Pojo(7,6,1),new Pojo(8,1,2),
        new Pojo(9,9,2),new Pojo(10,9,2),new Pojo(11,9,1),
        new Pojo(12,11,1),new Pojo(13,13,3),new Pojo(14,2,2)
);

首先按父级和orderNumber排序:

Collections.sort(list, (a,b) -> {

    if ( a.id == a.pId && a.pId == b.pId ) return -1;
    if ( b.id == b.pId && a.pId == b.pId ) return  1;

    // 100000... a number bigger there largest order#
    int aa = 100000 * a.pId + a.oNo;
    int bb = 100000 * b.pId + b.oNo;

    if ( aa > bb ) return  1;
    if ( aa < bb ) return -1;

    return 0;
});

然后循环前进,并且每行遍历到另一个pojo具有相同parentId的位置或其他pojo的id等于遍历pojo的parentId:

for ( int fw = 1 ; fw < list.size() ; fw ++ )
{
    Pojo a = list.get(fw);

    if ( a.id != a.pId )
    {
        for ( int bw = fw - 1 ; bw >= 0 ; bw -- )
        {
            Pojo b = list.get(bw);

            if ( a.pId != b.pId && a.pId != b.id )
            {
                list.set(bw, a);
                list.set(bw+1, b);
            }
            else
            {
                break;
            }
        }
    }
}

答案 1 :(得分:0)

这是一个依赖于上面评论中提到的树遍历的解决方案。这给出了线性时间性能,随着数据集大小的增加,它将变得更加相关。

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.*;
import java.util.function.*;

public  class PriorityTree {

    static class Node<T extends Comparable> implements Comparable{
        private T data;
        private Node<T> parent;
        private Collection<Node<T>> children;
        BiPredicate<Node<T>,T> addNodePredicate;
        UnaryOperator<T> paddingElement;

        public Node(T data, Node<T> parent, Collection<Node<T>> children,BiPredicate<Node<T>,T> addNodePredicate,UnaryOperator<T> paddingElement) {
            this.data = data;
            this.parent = parent;
            this.children = children;
            this.addNodePredicate = addNodePredicate;
            this.paddingElement = paddingElement;
        }

        public Node(T data, Node<T> parent) {
            this(data,parent,new TreeSet<Node<T>>(),parent.addNodePredicate,parent.paddingElement);
        }

        public boolean add(T element) {
            if (this.addNodePredicate.test(this,element)) {
                this.children.add(new Node<T>(element, this));
                return true;
            } else {
                for (Node<T> node : this.children) {
                    if(node.add(element)) return true;
                }
                return false;
            }
        }

        private String print(String indent){
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append(indent);
            stringBuilder.append(data);
            stringBuilder.append("\n");
            for (Node<T> node : this.children) {
                stringBuilder.append(node.print(indent+"  "));
            }
            return stringBuilder.toString();
        }


        @Override
        public String toString() {
            return print("");
        }

        @Override
        public int compareTo(Object o) {
            return this.data.compareTo(((Node<T>)o).data);
        }
    }

    static class Pojo implements Comparable{
        int id;
        int parentId;
        final int orderNo;

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

        public Pojo(int id, int parentId, int orderNo) {
            this(orderNo);
            this.parentId = parentId;
            this.id = id;
        }

        public Pojo(int orderNo) {
            this.orderNo = orderNo;
        }

        public int getId() {
            return id;
        }

        public int getParentId() {
            return parentId;
        }

        public int getOrderNo() {
            return orderNo;
        }

        public int compareTo(Object that) {
            if (that == null )return 1;
            if ( that instanceof Pojo)
                return Integer.compare(this.getOrderNo(),((Pojo)that).getOrderNo());
            else return 1;
        }

        static Pojo ROOT= new Pojo(0,0,0);

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;

            Pojo pojo = (Pojo) o;

            if (id != pojo.id) return false;
            if (parentId != pojo.parentId) return false;
            return orderNo == pojo.orderNo;
        }

        @Override
        public int hashCode() {
            int result = id;
            result = 31 * result + parentId;
            result = 31 * result + orderNo;
            return result;
        }
    }


    private static List<Pojo> readInObjects(String csvFile){
        final List<Pojo> list = new ArrayList<Pojo>();
        try{
            final FileReader fileReader = new FileReader(csvFile);
            final BufferedReader br =  new BufferedReader(fileReader);
            String line;
            while (( line = br.readLine()) != null) {
                final String[] valueArray = line.split(",");
                final int id = Integer.parseInt(valueArray[0]);
                final int parentId = Integer.parseInt(valueArray[1]);
                final int orderNo = Integer.parseInt(valueArray[2]);
                final Pojo pojo = new Pojo(id,parentId,orderNo);
                list.add(pojo);
            }

        }catch (IOException e) {
            e.printStackTrace();
        }
        return list;
    }

    public static void main(String[] args){
        final List<Pojo> values = readInObjects("values.txt");
        final Node<Pojo> tree = new Node<>(Pojo.ROOT, null, new TreeSet<>(), (pojoNode, pojo) -> pojoNode.data.getId()==0 && pojo.getId()==pojo.getParentId() ||pojoNode.data.getId() == pojo.getParentId(),(p)->new Pojo(0,p.getId(),0));
        values.stream().forEach(pojo -> tree.add(pojo));
        System.out.println(tree.toString());
    }
}

values.txt包含以下条目

1,1,1
2,1,1
3,2,1
4,3,1
5,2,3
6,5,1
7,6,1
8,1,2
9,9,2
10,9,2
11,9,1
12,11,1
13,13,3
14,2,2

输出看起来像

id=[1],parentId=[1],orderNo=[1]
  id=[2],parentId=[1],orderNo=[1]
    id=[3],parentId=[2],orderNo=[1]
      id=[4],parentId=[3],orderNo=[1]
    id=[14],parentId=[2],orderNo=[2]
    id=[5],parentId=[2],orderNo=[3]
      id=[6],parentId=[5],orderNo=[1]
        id=[7],parentId=[6],orderNo=[1]
  id=[8],parentId=[1],orderNo=[2]
id=[9],parentId=[9],orderNo=[2]
  id=[11],parentId=[9],orderNo=[1]
    id=[12],parentId=[11],orderNo=[1]
  id=[10],parentId=[9],orderNo=[2]
id=[13],parentId=[13],orderNo=[3]