Skiplist和strcpy以及AVL/红黑树

有点乱,是吧,确实,Skiplist怎么可能和strcpy联系在一起?

  确实,二者关联不大,但是二者最终的一个思想却是殊途同归的,背包算法的精髓在其中体现。本文不讲动态规划,也不讲背包算法,只是单纯的欣赏。

字符串拷贝

你要怎么把一个字符串拷贝到内存的一个位置?

  很简单,不是吗?你几乎天天调用,面试题也经常考,答案也是千篇一律,即便答错了一般也无所谓,答案几乎都是:

...
while(s++)
    *d++ = *s
...

这种。这样写对吗?当然对。但是这样写好吗?不好。

  如果我要拷贝一个4字节的字符串,是不是可以直接使用字拷贝指令呢?如果我拷贝5000字节的内容,并且我已经有一个超级高效的页面拷贝算法,是不是可以先拷贝一个4096字节的页面,然后再拷贝剩下的呢?剩下的是不是可以按照机器支持的最大处理长度分割,然后依次拷贝呢?最终我们的目标是,让拷贝的次数最少!嗯,这是一个典型的背包问题!如何解呢?答案在GNU的C库里。


Skiplist

现在来看跳表。

  我们希望有一个完全保持平衡的数据结构来保存数据,从而达到查找效率的最高点,选什么?很多人答曰红黑树。我不反对。

  但我觉得是Skiplist,因为它更优雅。这里不扯谁对谁错,你可以说Linux内核通用数据结构几乎都是红黑树,然而Redis为什么用Skiplist…这就好像你非要说奔驰比宝马好,而我觉得奥迪也不错一样,都差不多的东西,哪个更好纯属个人主观爱好了。

  红黑树需要在插入,删除的时候重新进行平衡操作,但是Skiplist并不需要,Why?

  因为它使用了一件利器,即概率。我们知道,独立事件是正态分布,关联事件是幂律,数据的插入显然是独立事件,即符合正态分布。

  我们知道,Skiplist的每一个元素均有 50%n 50 % n 的概率提升到 n n 层,那么第 n n 层有 m m 个节点的概率则为:

Pm×50%n P ≤ m × 50 % n

显然这个概率与第 n n 层具体的数据分布无关。因此在概率上,每一层的数据分布都是正态的,超级标准的。我们可以假设最终的Skiplist是下面的形状,它几乎在绝大多数情况下就是下面的形状:
Skiplist和strcpy以及AVL/红黑树_第1张图片

理想情况下(绝大多数情况都是理想情况!),查找操作 log log 级进行,这是和二叉树一致的,但是有没有发现,它竟然不需要做任何的平衡操作!相信概率即可。Skiplist倾斜的概率等于你连续 n n 此投掷硬币均显示正面!

   log log 级别skip节点,这不也是一种背包谜题的答案吗?和字符串拷贝一样,这里我需要寻找最少的比较次数,Skiplist不错!

AVL树

它太矜持了,同时又太较真儿,不说它。

你可能感兴趣的:(Skiplist和strcpy以及AVL/红黑树)