代码改变世界

一些STL 算法实现

2014-04-21 01:39  crazyxiazi  阅读(227)  评论(0)    收藏  举报

1.随机洗牌

保证每一个牌随机到任意位置的概率为1/n

for int i = n do swap(A[i],A[random(i,n)]);

 

一共的排列有n!种,如何证明其概率是 n!呢,有一种方式是这样的

第一次的概率是n第二次是n-1第三次是n-2故概率是n!。这个比较好理解,但是感觉不太能证明的感觉。

 

有一个证明如下,但是不太好理解:http://blog.csdn.net/cyningsun/article/details/7545679

第二种算法是符合要求的随机洗牌算法。

使用数学归纳法证明:

1、当n=1时,所以元素arr[0]在任何一个位置的概率为1/1,命题成立。

2、假设当n=k时,命题成立,即原数组中任何一个元素在任何一个位置的概率为1/k。

3、则当n=k+1时,当算法执行完k次时,前k个元素在前k个位置的概率均为1/k。当执行最后一步时,前k个元素中任何一个元素被替换到第k+1位置的概率为:(1-1/(k+1)) * 1/k = 1/(k+1); 在前面k个位置任何一个位置的概率为(1-1/(k+1)) * 1/k = 1/(k+1);故前k个元素在任意位置的的概率都为1/(k+1)所以,对于前k个元素,它们在k+1的位置上概率为1/(k+1)。对于第k+1个元素,其在原位置的概率为1/k+1,在前k个位置任何一个位置的概率为:(1-k/(k+1)) * (1/k)=1/(k+1),所以对于第k+1个元素,其在整个数组前k+1个位置上的概率也均为1/k+1。

 综上所述,对于任意n,只要按照方案中的方法,即可满足每个元素在任何一个位置出现的概率均为1/n。

 

2.快速排序:

STL的sort算法的优化策略:

1、  数据量大时采用QuickSort,分段递归排序。

2、  一旦分段后的数据量小于某个门槛,为避免Quick Sort的递归调用带来的额外负荷,就改用Insertion Sort。

3、  如果层次过深,还会改用HeapSort

4、  “三点中值”获取好的分割 采用的是从首、中点、尾三个元素中取中值来得到这个标志元素

 

3.堆排序:

建堆的过程

1.有从底向上 :

  1.   for(int i = (heapSize-1)/2; i >= 0; i--)  
  2.     {  
  3.         heapShiftDown(heap, i, heapSize );  //判断其i节点和i节点的左右节点是否有大小差别,若不是最大的则需要往下shift
  4.     } 

2.从顶向下

  1.  for(int i = 1; i < heapSize; i++)  
  2.     {  
  3.         heapShiftUp(heap, i);  
  4.     }  

4. 链表旋转:即ABCDEFG =》EFGABCD

1.双向旋转 DCBA GFE = 》EFGABCD

2.单向旋转: