Fork me on GitHub
序号的算法探讨

几乎没有哪个项目没有涉及到序号的使用,好的序号设计对减少代码量和执行效率有很大的作用。下面我将结合实际使用情况来对我遇到过的序号设计进行分析,也希望有更多人分享有关序号的设计与算法。

 

在简单的项目中,很多都是“自然排序”,数据的排序与数据本身有关,而没有人为干预,常见的有新闻或论坛中的根据时间或浏览量来排序。这种方式是最理想的排序方式,我们根本不需要增加一个序号字段来实现排序,只需要在显示时根据数据字段(如时间)来排序数据就好了。

事情总不会这么简单,有一天,你的新闻需要置顶功能了。那么,记录置顶就需要额外增加一个字段,在显示时会优先显示置顶的数据,我们暂且认为它已经在充当序号的角色。我们可以使用boolint型来标记它是否是置顶的,当然使用int来更好,因为不知道哪一天你的客户会告诉你我有很多置顶的数据,我对他们的顺序也要能够控制。

 

就这样,序号产生了,使用数字对置顶的新闻来排序。下面我们来讨论第一种需求:序号仅用于排序显示,用户不需要知道具体序号。

我将数据分成两种类型,来分别探讨哪种序号编码更为合适。

情景1:这是一个有大量数据组成的表,绝大多数数据不需要另行对其进行排序,我仅关心很少一部分数据的顺序。典型使用案例:新闻、论坛、文章系统。

这种情况下,设计序号时可以设计一个默认值,如0,来表示使用默认排序而不用另行处理,需要排序的部分使用大于(或小于)它的部分来排序,在修改序号变更时只需要变更影响排序的部分。当然,使用连续自增的数字来初始化排序也是可以的,当排序变化时,每次交换变化的两个的序号。由于不需要显示序号,所以删除时两种方式都不需要另行处理,但是使用连续自增的序号时在中间插入一个数据显然是比较痛苦的,即使使用算法(判断要插入的序号位置来决定是增加其之后的序号还是减少其之前的序号 或者 判断插入的这个序号是否存在,一直递归判断到该序号未使用为止),它的最坏情况需要对(n/2 + 1)条数据进行更新,n为数据总数;如果使用默认值的话,它即使不使用算法来优化,最坏情况也只需要对(m+1)条数据进行更新,m为排序过的数据。根据情景可以知道mn要小的多。

 

情景2:这是一个只有少量数据组成的表,用户对其排序比较频繁,对每一条数据几乎都会有排序的需求。典型应用:网站栏目、用户导航栏、菜单等。

由于数据较少,使用何种序号设计对性能的影响并不大,因此我仅提出一种优化过的序号设计,而不对其与其它方式进行比较分析。在初始化序号时,采用有一定间隔的序号。具体间隔需要根据插入数据的可能性进行设计,比如我的网站栏目无论怎么增长,在未来几年里都不可能新增超过100各栏目,我把栏目的序号使用100的倍数来初始化,这样,在交换、新增、删除操作中对数据需要更新的最多会涉及到操作的数据与和它相邻的数据。

 

你也许会觉得这太简单了,序号也不过如此吗。有一天,老板让你把序号显示出来,于是,前面乱七八糟的序号又得进行大换血了。

 

下面我仍然根据数据的多少分成两种情况讨论:

情景3:我有大量数据进行排序,数据需要分页。这种情况下又会派生出两种显示需求,第一种:分页后的数据的序号接着上一页的序号显示;第二种:分页后的数据从头开始排序。

这两种需求都比较常见,我们根据两种不同实现序号效果的方式来分析。

1,数据库存储序号与显示序号无关,数据库仅存储用于排序;显示的序号在数据加载显示时增加。这种方式两种显示需求都适用,序号设计可以参考情景1

2,数据存储的序号就是显示的序号。在这种实现模式下,必须适用连续的序号对数据进行初始化,在修改序号、新增、删除数据时都会影响排在它之后的数据,最坏的情况下每次操作需要更新(n+m)条数据,n为数据总数,m为新增的数据数,带来的好处是在数据加载时不需要程序干预。这种方式第二种需求不适用,而且需要用户能够接受网格筛选过滤带来的序号不连续情况。

 

情景4:少量数据进行排序显示。这种情况下与情景3的区别不大,只是可能会较少遇到需要分页的情况,网格筛选过滤也不常用,因此情景3的两种实现方式都可以使用。

 

以上介绍了几种经常使用的序号情景,当然还有很多其它用于特殊情况下的序号设计,我仅列出设计思路而不对其进行分析。

1,使用不重复的定序号确定该数据在数据中的绝对位置;

2,使用内序号与显示序号结合实现排序(树上使用较多);

3,在文件中存储特定用户的排序信息(个性化)。

 

当然,了解序号设计并不能让你写出有序的序号算法,一个好的网格操作需要尽可能少的数据交互,特别是在网络条件并不好的情况下。你应该设法实现网格的单行刷新、多行刷新、删除、新增等操作的数据刷新操作,而不是每次改变数据并重新读取所有数据来刷新显示的内容。这样你在更新序号时仅仅需要将update语句传到数据库,而显示部分已经由程序逻辑处理好了。这样即使你的序号设计再烂,它对你程序效率的影响也是有限的。

 

posted on 2013-09-23 23:03  HackerVirus  阅读(577)  评论(0编辑  收藏  举报