用于维护用于排序数据库元素的“排序字符串”的算法

时间:2012-06-07 07:44:25

标签: database algorithm google-app-engine

我有一个数据库,我想在其中存储特定元素的任意顺序。有问题的数据库不支持订单集,所以我必须自己做。

执行此操作的一种方法是为元素的位置存储浮点值,然后在插入新元素时获取周围元素的平均位置:

Item A - Position 1
Item B - Position 1.5  (just inserted).
Item C - Position 2

现在,由于各种原因我不想使用花车,我想用字符串代替。例如:

Item A - Position a
Item B - Position aa  (just inserted).
Item C - Position b

我希望尽可能缩短这些字符串,因为它们永远不会“整理”。

有人能建议一种尽可能高效,紧凑地生成此类字符串的算法吗?

谢谢,

3 个答案:

答案 0 :(得分:1)

将“am”或“an”位置分配给项目B并使用二进制除法步骤进行其他插入是合理的。 这类似于26-al数字系统,其中'a'..'z'符号对应于0..25。

a b   //0 1
a an b  //insert after a  - middle letter of alphabet  
a an au b  //insert after an
a an ar au b  //insert after an again (middle of an, au)
a an ap ar au b   //insert after an again
a an ao ap ar au b //insert after an again
a an ann ao...  //insert after an, there are no more place after an, have to use 3--symbol label
....
a an anb...  //to insert after an, we treat it as ana
a an anan anb  // it looks like 0 0.5 0.505 0.51  

二叉树结构的伪代码:

function InsertAndGetStringKey(Root, Element): string
  if Root = nil then
    return Middle('a', 'z') //'n'

  if Element > Root then
    if Root.Right = nil then
      return Middle(Root.StringKey, 'z') 
    else
       return InsertAndGetStringKey(Root.Right, Element)   

  if Element < Root then
    if Root.Left = nil then
      return Middle(Root.StringKey, 'a') 
    else
       return InsertAndGetStringKey(Root.Left, Element) 

Middle(x, y): 
  //equalize length of strings like (an, anf)-> (ana, anf)
  L = Length(x) - Length(y)
  if L < 0 then
    x = x + StringOf('a', -L) //x + 'aaaaa...' L times
  else if L > 0 then
    y = y + StringOf('a', L)  

  if LL = LastSymbol(x) - LastSymbol(y)  = +-1 then
    return(Min(x, y) + 'n')  // (anf, ang) - > anfn
  else
    return(Min(x, y) + (LastSymbol(x) + LastSymbol(y))/2) // (nf, ni)-> ng

答案 1 :(得分:0)

如上所述,问题没有解决方案。一旦算法为相邻元素生成字符串'a'和'aa',就没有可以在它们之间插入的字符串。这是该方法的致命问题。此问题与用于字符串的字母表无关:如果您愿意,请将“a”替换为“使用的字母表中的第一个字母”。

当然,当达到这个僵局时,可以通过更改其他元素的排序字符串来解决它,但这似乎超出了OP的要求。

我认为问题等同于找到一个整数来表示一个元素的顺序,并发现35和36已经用于命令现有元素。无论你多么努力,都没有35到36之间的整数。

使用实数或计算机近似值,例如浮点数或有理数。

编辑以回应OP的评论

只需调整算法以添加2个有理数:(a / b)+(c / d)=(ad + cb)/ bd。拿(ad + cb)/ 2(如果你想要或需要四舍五入)你在前两个中间有一个合理的中间位置。

答案 2 :(得分:0)

资本是一种选择吗?

如果是这样,我会用它们在相邻的值之间插入。

例如插入之间 一个 AA

你可以这样做:

aAaa&lt; ---这个上限。告诉我们在相邻的小值之间还有一个地方.ie。一个[AA]一个

AABA

AACA

ABAA

ABBA

AA

现在,如果你需要在a和aAaa之间插入

你可以做到

aAAaaa&lt; --- 2 caps。告诉我们在相邻的小值之间还有两个位置,即[AAaa] a

aAAaba

aAAaca

...

aAAbaa

AAAA

在紧凑或高效方面,我没有提出任何要求......