【问题标题】:Sorting Parent-Children relations排序亲子关系
【发布时间】:2015-10-21 06:43:34
【问题描述】:

我在为我的班级 Page 找出一个简单的 compareTo 方法时遇到了一些问题:

  • 页面通过 getParent() 引用了父页面 - 可以为空
  • 页面有一个变量order,只决定同层级的顺序

我喜欢按以下方式排序:

  1. 父A
  2. SubParentOfA1
  3. SubParentOfA2
  4. 父B
  5. 父C
  6. SubParentOfC1
  7. SubParentOfC2

我的 compareTo 需要如何解决这个问题?我尝试了以下,目前只能正确排序相同的级别。

我的做法:

@Override
public int compareTo(@NonNull Object o) {
    int compare = 0;
    if (o instanceof Page) {
        Page other = (Page) o;
        if (other.parent != null) {
            compare = this.compareTo(other.parent);
        } else if (parent != null) {
            compare = this.parent.compareTo(other);
        }
        if (compare == 0) {
            compare = Integers.compareTo(this.order, other.order);
        }
    }
    return compare;
}

编辑:我的页面类:

class Page{
    int order;
    Page parent;
}

【问题讨论】:

  • 您永远不会将 this.parentother.parent 进行比较。您可以添加级别属性(存储为属性或动态计算)以方便比较。
  • 当他们中的一个没有父母时,我不就这样做吗?我递归调用 compareTo 直到我处于顶层。

标签: java sorting tree


【解决方案1】:

您可以简单地依赖order链,而不是进行复杂的计算。我使用了String 来存储每个“节点”的链:

class Page implements Comparable<Page> {
    String name;
    int order;
    Page parent;
    String key;

    Page() {
        name = "root";
        order  = 0;
        parent = null;
        key    = "";
    }

    Page(String name, int order, Page parent) {
        this.name   = name;
        this.order  = order;
        this.parent = parent;
        key = parent.key + (char)order;
    }

    @Override
    public int compareTo(Page o) {
        return key.compareTo(o.key);
    }

    @Override
    public String toString() {
        return name;
    }
}

public static void main(String[] args) {
    Page root = new Page();

    Page b    = new Page("b"  , 2, root);
    Page b1   = new Page("b.1", 1, b);
    Page b3   = new Page("b.3", 3, b);
    Page b2   = new Page("b.2", 2, b);

    Page a    = new Page("a"  , 1, root);
    Page a2   = new Page("a.2", 2, a);
    Page a1   = new Page("a.1", 1, a);

    List<Page> pages = Arrays.asList(root, a, a1, a2, b, b1, b2, b3);
    System.out.println(pages);

    Collections.shuffle(pages);
    System.out.println(pages);

    Collections.sort(pages);
    System.out.println(pages);
}

这里的技巧是使用String 作为可排序的short 数组。该数组是order 的复合物,它形成了从根到节点的路径。 root 的键/id 为 []a 来自 root 的子级,order 1 作为 [1] 的键/id。

这里是键/id 矩阵:

┌──────┬────────┬───────┬────────────┬─────┐
│ Page │ Parent │ Order │ Parent Key │ Key │
├──────┼────────┼───────┼────────────┼─────┤
│ root │ -      │ -     │ -          │     │
│ a    │ root   │ 1     │            │ 1   │
│ a.1  │ a      │ 1     │ 1          │ 1 1 │
│ a.2  │ a      │ 2     │ 1          │ 1 2 │
│ b    │ root   │ 2     │            │ 2   │
│ b.1  │ b      │ 1     │ 2          │ 2 1 │
│ b.2  │ b      │ 2     │ 2          │ 2 2 │
│ b.3  │ b      │ 3     │ 2          │ 2 3 │
└──────┴────────┴───────┴────────────┴─────┘

这是来自另一棵树的示例(括号中的键)

root      (     )
├ z       (1    )
│ ├ a     (1 1  )
│ │ └ y   (1 1 1)
│ └ b     (1 2  )
│   └ x   (1 2 1)
└ c       (2    )
  ├ w     (2 1  )
  └ d     (2 2  )

【讨论】:

  • 这不依赖于我的父页面的命名方式吗?有一个按字母顺序排序的列表只是一个例子。一个名为“c”的页面可能有一个名为“a”的子页面,反之亦然
  • 它不依赖字母顺序。请参阅我的详细编辑。您可以自己尝试该示例以检查代码行为...
【解决方案2】:

你可能有检测页面深度的方法

解决办法是这样的:

public class Page {
    private int order;
    private Page parent;

    public Page() {
    }

    public Page(int order, Page parent) {
        this.order = order;
        this.parent = parent;
    }

    public int getOrder() {
        return order;
    }

    public void setOrder(int order) {
        this.order = order;
    }

    public Page getParent() {
        return parent;
    }

    public void setParent(Page parent) {
        this.parent = parent;
    }


    public int compareTo(Object o){
        int compare = 0;
        if (o instanceof Page) {
            Page other = (Page) o;
            if(this.depth() == other.depth()){
                if(Objects.equals(this.getParent(), other.getParent())){
                    return Integer.compare( other.getOrder(),this.getOrder());
                }
                else{
                    return this.getParent().compareTo(other.getParent());
                }
            }
            else{
                return Integer.compare(other.depth() , this.depth());
            }
        }
        return compare;
    }

    public int depth(){
        if(this.parent == null)return 0;
        else return 1+this.parent.depth();
    }

    public static void main(String[] args){
        Page a = new Page(1, null);
        Page a_1 = new Page(1, a);
        Page a_2 = new Page(2, a);
        Page a_1_1 = new Page(1, a_1);
        Page a_1_2 = new Page(2, a_1);
        Page a_2_1 = new Page(1, a_2);
        Page a_2_2 = new Page(2, a_2);

        System.out.println(a_1.compareTo(a_1_1));
        //1 because a_1 has higher depth
        System.out.println(a_1.compareTo(a_2));
        //1 because a_1 has smaller order
        System.out.println(a_1_2.compareTo(a_1_1));
        //-1 because a_1_2 has higher order
        System.out.println(a_2_1.compareTo(a_1_1));
        //-1 because a_2_1 parent is a_2 and a_1_1 parent is a_1
    }
}

【讨论】:

  • 我以某种方式尝试在 compareTo 中解决它,甚至没有考虑使用辅助方法:/欢呼!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-30
  • 1970-01-01
  • 2012-05-07
  • 1970-01-01
相关资源
最近更新 更多