遍历引用Java

时间:2016-08-20 19:07:15

标签: java android algorithm tree

我正在尝试使用https://github.com/bmelnychuk/AndroidTreeView

创建一个Hierarchical菜单

我将从REST服务中检索我的数据,示例菜单如下所示

[
  {
    "name": "parent 1",
    "code": "p1",
    "parent_code": "null",
    "is_active": 1,
    "store_id": "57a6d06232a7d133002b838c"
  },
  {
    "name": "parent 2",
    "code": "p2",
    "parent_code": "null",
    "is_active": 1,
    "store_id": "57a6d06232a7d133002b838c"
  },
  {
    "name": "child 1",
    "code": "c1",
    "parent_code": "p1",
    "is_active": 1,
    "store_id": "57a6d06232a7d133002b838c"
  },
  {
    "name": "child 2",
    "code": "c2",
    "parent_code": "p1",
    "is_active": 1,
    "store_id": "57a6d06232a7d133002b838c"
  },
  {
    "name": "grand child 1",
    "code": "gc1",
    "parent_code": "c2",
    "is_active": 1,
    "store_id": "57a6d06232a7d133002b838c"
  },
  {
    "name": "grand child 2",
    "code": "gc2",
    "parent_code": "c2",
    "is_active": 0,
    "store_id": "57a6d06232a7d133002b838c"
  },
  {
    "name": "grand child 3",
    "code": "gc3",
    "parent_code": "c2",
    "is_active": 1,
    "store_id": "57a6d06232a7d133002b838c"
  }
]

我正在尝试遍历List并创建一个Hierarchical菜单。我正在使用以下代码

for (ProductCategory prodCat :
                productCategories)
{
    if (prodCat.getParentCode().equalsIgnoreCase("null"))
    {
        // I found a parent node
        for (ProductCategory prodCatChild :
                productCategories)
        {
            if (prodCatChild.getParentCode().equalsIgnoreCase(prodCat.getCategoryCode()))
            {
                //I found all child nodes of the current parent
            }
        }
    }
}

我的ProductCategory定义如下

public class ProductCategory
{
    private String categoryName;

    private String categoryCode;

    private String parentCode;

    private Boolean isActive;

    private String storeId;
}

这段代码有两个问题。

  • 如果树中有第三级或更多级别,我根本无法遍历它们。
  • 我在两个级别上遍历n ^ 2次。

如何以最有效的方式遍历仅提及父母的行为?

1 个答案:

答案 0 :(得分:2)

我建议您使用Hash Map数据结构来构造具有 O(N)运行时复杂性的树。

为简单起见,我们假设您的实体具有以下结构(为了简单起见,我还违反了提供的代码片段中的封装原则):

class Item {

    // id of the item itself
    final String id;

    // id of the parent item
    final String parentId;

    // this list will contain the children of the given item
    // at the beginning this list is empty, and we are going to populate it
    final List<Item> children = new ArrayList<>();

    public Item(String id, String parentId) {
        this.parentId = parentId;
        this.id = id;
    }
}

为了构造树,您应该保持从item id到项本身的映射(可以使用 java.util.HashMap 数据结构完成)。构建映射后,您可以将每个节点附加到其父节点:

List<Item> constructForest(Item... items) {
    Map<String, Item> itemIdToItem = indexItemsById(items);
    List<Item> roots = attachToParents(itemIdToItem, items);
    return roots;
}

/**
 * Index all items by item id.
 * Returns the mapping from the item id to item.
 */
Map<String, Item> indexItemsById(Item... items) {
    Map<String, Item> itemIdToItem = new HashMap<>();
    for (Item item : items) {
        itemIdToItem.put(item.id, item);
    }
    return itemIdToItem;
}

/**
 * Attaches the children nodes to the parent nodes
 * Returns the list of root nodes of the constructed forest
 */
List<Item> attachToParents(Map<String, Item> itemIdToItem, Item... items) {

    List<Item> roots = new ArrayList<>();

    for (Item item : items) {
        if (item.parentId == null) {
            roots.add(item);
        } else {
            Item parent = itemIdToItem.get(item.parentId);
            parent.children.add(item);
        }
    }

    return roots;
}

提供的代码的运行时复杂性为 O(N)

现在,拥有构造树的根列表,您可以使用任何树遍历算法遍历它们,例如广度优先搜索(https://en.wikipedia.org/wiki/Breadth-first_search),深度优先搜索(https://en.wikipedia.org/wiki/Depth-first_search),其运行时复杂度 O(N)