暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

树形结构如何排序

writeline 2021-10-11
4576

今天来聊一聊树形结构如何排序。

1.1 需求

现在要求实现一个菜单功能。而这个菜单会有层级关系,因此整个结构呈现出来的话,就是一颗树。这个功能相信大多数人都是做过的。很简单对吧。但是现在在加上一个功能,需要实现任意拖拽,你可以拖拽一个节点也可以是一颗子树。并且拖拽后的顺序要保持住。

1.2 理解消化需求

需求消化下就是两点:

  • 实现菜单的树级结构
  • 支持任意拖拽后的顺序保存

我们从java
语言层面的设计出发,要实现一颗树,我们很快就能想到的结构便是:

idpidname
10我是父菜单
21我是子菜单
32我也是子菜单

最终效果:

  • 我是父菜单
    • 我是子菜单
    • 我也是子菜单

那排序呢,要怎么来做?具体编码我不知道,但是肯定这个顺序肯定要保存起来的吧!因此我可以在调整下结构:

idpidnamesort
10我是父菜单0
21我是子菜单2
32我也是子菜单1

最终效果:

  • 我是父菜单
    • 我也是子菜单
    • 我是子菜单

也就是呈现节点时,可以根据这个sort
来排序。

1.3 排序再思考

经过上面的思考后,我们对需求已经比较了解了,而且具体的实现也有一点底了。那到底要怎么去实现呢?菜单保存就不讨论了,主要就第2个问题,如何实现排序来展开探讨。可以先弄点数据来推导这个过程,

idpidname
10菜单1
21菜单2
32菜单3
42菜单4
52菜单5
62菜单6
70菜单7

最终效果:

  • 菜单1
    • 菜单3
    • 菜单4
    • 菜单5
    • 菜单6
    • 菜单2
  • 菜单7

问题1:现在假定要把菜单3移动到菜单4后面
需要传递的参数有:

  • id     #当前移动的节点 id
  • pid    #当前移动的父节点 id
  • index  #移动的位置索引

从上面的效果图来看,菜单3和菜单4就是对调下位置。更改一下对应的sort
值即可。其他的都不用变化。

那我们可以知道,如果要移动的菜单和目标菜单的pid
一样的话,那只要变更下sort
位置即可。这个很简单。

问题2:把菜单7移到菜单2下面
需要传递的参数同上。

在结合上面的效果图来看,菜单7移到菜单2下面,可以这样做,

  • 根据菜单7的pid
    获取pid
    =菜单7.pid
    的菜单列表,并将菜单7移除,同时对列表进行排序。这里是外部的排序。
  • 根据菜单2的pid
    获取pid
    =菜单2.pid
    的菜单列表,需要判断菜单列表的个数是否大于要移动的索引数,大于的话,可以直接按照索引添加元素;小于的话,直接添加。然后可以重新计算下sort
    值。这里是内部的排序。

好像到这里,就已经可以了。很简单。但这里需要变更的菜单比较多。

除此之外呢,还有其他的算法吗?

设想一下,菜单创建的时候是有序的。而菜单在移动的过程中是部分有序的,可以做到最小化移动。在来看下效果图,

  • 菜单1
    • 菜单3
    • 菜单4
    • 菜单5
    • 菜单6
    • 菜单2
  • 菜单7

问题1:现在假定要把菜单3移动到菜单4后面

这里只需要更改菜单3的sort
值,只要它的sort
值比菜单4要小,那不就实现了我们的要求了吗?

问题2:把菜单7移到菜单2下面

思考:根据菜单2的pid
获取pid
=菜单2.pid
的菜单列表。在根据要移动的位置,来更改sort
值。而这个sort
值又该怎么更新呢?如果现在不更改其他菜单,就只变更当前要移动菜单的sort
值。如果sort
值是这样分布的:

  • 菜单1      10
    • 菜单3  101010
    • 菜单4  101011
    • 菜单5  101012
    • 菜单6  101013
    • 菜单2    1010
  • 菜单7      11

移动后会是这样:

  • 菜单1      10
    • 菜单7  101009
    • 菜单3  101010
    • 菜单4  101011
    • 菜单5  101012
    • 菜单6  101013
    • 菜单2    1010

不过这样还是会有问题的。例如现在某个菜单要移动到菜单4,5之间,那sort
值又该怎么来定?

1.4 总结

的确,按照第一种方法来实现树形结构的排序是最简单的。按照第二种的话,sort
值的区间怎么来定呢?还有第三种、第四种吗?

本篇分享先到这里,欢迎关注。

如有收获,点个在看,诚挚感谢
文章转载自writeline,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论