【问题标题】:How to sort tree of folders如何对文件夹树进行排序
【发布时间】:2014-05-25 09:18:28
【问题描述】:

我有一个文件夹平面树。该树具有以下属性:id、parent_id、name。

我将这棵树存储在一个简单的数组中。问题是这个数组没有排序。

我的数组的一个元素是这样的简单对象:

var obj = { id: 1, parent_id: null, name: "Folder" }

我想对它进行排序,以便能够看到这样的东西:

Folder1
  Sub_folder1
    Sub_sub_folder1
  Sub_folder2
    Sub_sub_folder2

还有一个……我不想使用递归,也不知道如何正确使用。

这是我的一些尝试。我尝试添加一个人工字段,该字段将表示集合中每个文件夹的数量,但它不起作用。

var sort = function(list) {

  var f_map = {};
  var sorting_index = 1;
  var tree = angular.copy(list);

  for(var i = 0; i < tree.length; i++) {

    var node = tree[i];
    f_map[ node.id ]= { index: i, children: [] };

    if (node.parent_id) {
      f_map[ node.parent_id ].children.push( node.id );
    };

    var idx = 0;
    var visited = {};

    for(var key in f_map) {
      var index = f_map[key].index;
      var node = tree[index];
      if (!visited[node.id]) {
        node.nuid = idx++;
      } else {
        visited[node.id] = true;
      };
      if (f_map[key].children.length) {
        var children = f_map[key].children;
        for(var i = 0; i < children.length; i++) {
          var child_id = children[i];
          var child_idx = f_map[child_id].index;
          var child = tree[child_idx];
          child.nuid = idx++;
          visited[child.id] = true;
        };
      };
    };

    tree.sort(function(left, right) {
      return left.nuid - right.nuid;
    });

    return tree;
};

【问题讨论】:

  • 请在代码示例中添加您尝试过的内容。很乐意帮助您遇到困难,但不会为您解决。另外,如果你不知道怎么做,那你为什么选择退出递归呢?
  • @Ronni Skansing,完成。不想使用递归,因为这样做会让一切变慢。
  • 你的阵列是什么样的?要对树结构进行排序,您可以按节点的路径排序、使用递归或使用堆栈(即手动实现递归)。
  • @thebjorn 添加了对我的数组元素的小描述。不知道如何正确使用堆栈。你有例子吗?
  • 递归可能比您认为的要快得多 - 不要假设它不能满足您的速度要求。

标签: javascript arrays algorithm sorting


【解决方案1】:

由于您将父指针表示为对父节点的 id 的引用,因此我首先将您的文件夹表示更改为对象表示:

var folders = {
    1: {parent_id: null, name: "Folder", path: null},
    ...
};

我添加了一个path 字段,以便我可以记住以下递归函数的结果以查找文件夹的完整路径:

function path(node) {
    if (node.path !== null) return node.path;
    if (node.parent_id === null) {
        node.path = '/' + node.name;
    } else {
        node.path = path(folders[node.parent_id]) + '/' + node.name;
    }
    return node.path;
}

然后我们可以通过首先拉出我们想要排序的字段和对该项目的引用来进行 Schwartzian 变换:

var keys = [];

Object.keys(folders).map(function (key) {
    var folder = folders[key];
    keys.push({path: path(folder), id: key});
});

然后我们可以对键数组进行排序:

keys.sort(function (a, b) {
    var apath = a.path;
    var bpath = b.path;

    // probably the best way to compare folder paths..
    return apath.localeCompare(bpath);
});

最后我们可以通过遍历keys数组以排序的方式生成文件夹:

var sorted_folders = keys.map(function (item) {
    return folders[item.id];  // .name; or maybe .path; ??
});

sorted_folders 将是文件夹对象的列表,但根据评论,您可以在此步骤中轻松提取所需的属性。

【讨论】:

    【解决方案2】:

    首先,递归并不慢。这是您的武器库中的一个不错的工具。它使解决某些问题变得更加容易。

    这是一个应该解决它的算法。

    1. If the graph can be a forest and not a tree
           create a new node root
           Make all roots in forest point to this root as parent
    2. For every node, create an array (stack) of its children, call it c[i].
    3. For each vertex v in tree
           c[v.parent].push(v)
    4. u = root, i = 0
    5. print u
    6. while c[root] is not empty and u != root
           if c[u] is not empty
               u = pop(c[u])
               i++
               print tab i times
               print u
           if c[u] is empty and u != root
               u = u.parent
               i--
    

    【讨论】:

      猜你喜欢
      • 2013-02-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-08
      • 1970-01-01
      • 1970-01-01
      • 2019-03-11
      • 2012-12-25
      相关资源
      最近更新 更多