链接https://www.evernote.com/shard/s408/sh/dbe0167f-20e0-41c4-a49b-75717ad98695/461148482ffb6add092bebc9d90a4a2a
 
 搜索和排序一项是算法的两大主题,重要性不言而喻。Robert在第一周的lecture 2就是从基本的排序算法说起。包括选择排序(应该也叫冒泡排序)、插入排序,希尔排序(Shell Sort),附带讲了shuffle(随机序列),以及凸集。我们一点点说。


零、Total Order

A total orderis a binary relation ≤that satisfies:
1。Antisymmetry: if v ≤ w and w ≤ v, then v= w.
2。Transitivity: if v ≤ w and w ≤ x, then v ≤ x.

3。Totality: either v ≤ w or w ≤ vor both.


一、选择排序
 
如下原始序列:
   a= [ 9 2 1 4 8 7 5 6 3]
           i=0
经过一次swap
  a= [ 1 2 9 4 8 7 5 6 3]
            i=1
经过两次swap(索引1和索引1交换)
  a= [ 1 2 9 4 8 7 5 6 3]
               i=2
从序列中选出最小的 也就是1,索引为2,a[i]与a[2]交换,i=i+1,从余下的序列中再选出最小的,也即2,a[1]与a[1]交换,也即保持不动,循环知道最后一个元素,c#简单代码:
        public void SelectSort(ref int [] a)
        {
            int count = a.Length;
            for ( int i = 0; i < count; i++)
            {
                int min = i;
                for ( int j = i+1; j <count; j++)
                {
                    if (a[j] < a[min]) min = j;
                }
                Swap( ref a, i, min);
            }
        }
        public void Swap( ref int[] a , int i, int j)
        {
            int temp = a[i] ;
            a[i] = a[j];
            a[j] = temp;
        }
选择最小值需要比较的次数 N-1+N-2+……+2+1+0 ~N^2/2,元素交换的次数N。
即使输入时已经排序好的,也要经过Quadratic time。数据移动是线性的,而且不需要额外空间。

二、插入排序
如下原始序列:
   a= [ 9 2 1 4 8 7 5 6 3]
           i=0
经过一次插入
  a= [ 2 9 1 4 8 7 5 6 3]
            i=1
经过两次插入
  a= [ 1 2 9 4 8 7 5 6 3]
               i=2
不描述过程,太难了,直接看代码吧
       public void Swap( ref int[] a ,int i,int j)
        {
            int temp = a[i] ;
            a[i] = a[j];
            a[j] = temp;
        }
        public void InsertSort( ref int[] a)
        {
            int count = a.Length;
            for ( int i = 0; i < count; i++)
            {
                for ( int j = i; j > 0; j--)
                {
                   if(a[j]<a[j-1]) Swap( ref a, j,j-1);
                    else break;
                }
            }
        }
用插入排序,对于个随机的数列,需要1/4*N^2比较和1/4*N^2次交换,不需要额外空间。
如果输入序列式最好的,即已经升序排好的,只需N-1次比较和0次交换
最坏情况,如果输入是降序排好的,将需要1/2*N^2次比较和1/2*N^2交换

三、shell排序
感觉shell排序和插入排序差不多,算是插入排序的一种,和插入排序不同,shell排序每次不是和后继元素比较,而是和一定步长之后的元素比较,每个元素都如此,一轮过后,缩小步长,继续知道步长为1,此时也就是插入排序,得出结果。
根据数据大小来选择步长,步长一般有:
1.  1,2,4,8,16......也就2的幂
2.  1,3,7,15....2的幂减1
3. 3x+1,即1,4,13,40,121....
还有就是
4. Sedgewick. 1, 5, 19, 41, 109, 209, 505, 929, 2161, 3905, …
 
据robert介绍,1不行,2一般,3还好,4最好(也就是他自己提出的)。没有证明~~~
方便写代码,用3的步长~~
         public void ShellSort( ref int[] a)
        {
            int count = a.Length;
            int h =1;
            while (h < count / 3) h = h * 3 + 1; //先找到最大的步长
            while (h>=1)
            {
                for ( int i = 0; i+h<count; i++)//ps纸上得来终觉浅,这一步没写好,因为a[i]和a[i+h]比较后,如果a[i+h]小于a[i],那么a[i+h]要继续和
                {                               //a[i]之前的元素比较,以前我以为不需要呢,所以搞错了。需知此事要躬行啊啊啊
                    for ( int j = i + h; j >=h && a[j] < a[j - h]; j--)
                    {
                        Swap( ref a, j, j - h);
                    }
                }
                h = h / 3;
            }
        }
    
Proposition. The worst-case number of compares used by shellsort with
the 3x+1 increments is O(N3/2).
 
希尔排序目前还没有accurate model!!!
为什么对希尔排序感兴趣?
 
1.现实中,对于较小的序列,排序很快,可以用在嵌入式系统
2.虽然是简单的算法,但性能很不错。而且还有很多问题未解决,如算法的渐进增长率、最佳步长序列,平均性能。
3.所以说,还有好的算法等待发现。
 

四、随机序列
比较简便的方法是:
1 2 3 4 5 6 7 8 9
对于该序列,每一个数字都随机生成一个随机数,然后按随机数大小排序。
 
Proposition. Shuffle sort produces a uniformly random permutation
of the input array, provided no duplicate values,where assuming real numbers uniformly at random
 
Knuth提出的一个方法是:在第i次迭代时,随机选择0到i之间的整数r,然后交换a[i]和a[r].
Proposition:Knuth的shuffle算法能在线性时间能得到一个均匀随机数列。
便于分析,从i=1开始,考虑第一个元素,也就考虑索引为1位置的元素
在开始第1次时
i=1;r=1; 索引1的元素保持不变
在第2次时
i=1,2,索引1 和 2交换位置的概率为1/2,索引1的元素在1或者2位置上的概率是1/2
在第3次时
i=1,2,3,原始1位置上的元素换到第三个位置上的概率1/2*1/3+1/2*3=1/3
同理,第4次
i=1,2,3,4 原始1位置的元素,在每个位置上的概率 1/3*1/4+1/3*1/4+1/3*1/4=1/4
依次推下去可医治,每个元素在任意位置的概率为1/N。
简单代码如下
public static void shuffle(ref int[] a)
{
int N = a.length;
for (int i = 0; i < N; i++)
{
int r = Random(i + 1);
swap(ref a, i, r);
}
}
一个实例,online poker 在线扑克的程序bug。
做到真正的shuffle其实挺难的。也可以依赖硬件,随机数产生器blabla不叙说了。

五 凸集
 
实数 R (或复数 C 上)在向量空间中,如果 S 中任两点的连线内的点都在集合 S 内,集合 S 称为凸集。
一个直白叙述就是,从一个点开始,可以一直逆时针找到一个点,点与点连线,能将所以点都包住。
下面就是凸集。
 
 
懒得写了,给出三个点序,a->b->c,怎么判断是否是逆时针顺序的
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

跟着Sedgewick学算法(week 1 ElementarySort)的更多相关文章

  1. 跟着Sedgewick学算法(week 1 UnionFind)

    发现笔记转过来,没有图的~~~~~~~~~~~悲剧,给出共享笔记链接 https://www.evernote.com/pub/yanbinliu/algorithm 很久之前就在coursera看到 ...

  2. 1164: 零起点学算法71——C语言合法标识符(存在问题)

    1164: 零起点学算法71——C语言合法标识符 Time Limit: 1 Sec  Memory Limit: 64 MB   64bit IO Format: %lldSubmitted: 10 ...

  3. 1163: 零起点学算法70——Yes,I can!

    1163: 零起点学算法70--Yes,I can! Time Limit: 1 Sec  Memory Limit: 64 MB   64bit IO Format: %lldSubmitted: ...

  4. 1147: 零起点学算法54——Fibonacc

    1147: 零起点学算法54--Fibonacc Time Limit: 1 Sec  Memory Limit: 64 MB   64bit IO Format: %lldSubmitted: 20 ...

  5. 1145: 零起点学算法52——数组中删数II

    1145: 零起点学算法52--数组中删数II Time Limit: 1 Sec  Memory Limit: 64 MB   64bit IO Format: %lldSubmitted: 293 ...

  6. 1137: 零起点学算法44——多组测试数据输出II

    1137: 零起点学算法44--多组测试数据输出II Time Limit: 1 Sec  Memory Limit: 64 MB   64bit IO Format: %lldSubmitted: ...

  7. 1136: 零起点学算法43——多组测试数据输出I

    1136: 零起点学算法43--多组测试数据输出I Time Limit: 1 Sec  Memory Limit: 128 MB   64bit IO Format: %lldSubmitted: ...

  8. 1135: 零起点学算法42——多组测试数据(求和)IV

    1135: 零起点学算法42--多组测试数据(求和)IV Time Limit: 1 Sec  Memory Limit: 64 MB   64bit IO Format: %lldSubmitted ...

  9. 1134: 零起点学算法41——多组测试数据(a+b)III

    1134: 零起点学算法41--多组测试数据(a+b)III Time Limit: 1 Sec  Memory Limit: 64 MB   64bit IO Format: %lldSubmitt ...

随机推荐

  1. 在.net2.0中实现Action和Func方法

    由于这两个是在.net3.5中新加入的特性,所以我们需要自己写一下. 格式如下: delegate void Action();        delegate void Action<T, T ...

  2. 【linxu】部署docker容器虚拟化平台

    实验所涉内容 Docker 概述 部署 docker 容器虚拟化平台 docker 平台基本使用方法 创建docker镜像和发布镜像方法 Container 容器端口映射 一 Docker 概述 Do ...

  3. Hexo NexT主题添加点击爱心效果

    给NexT主题内添加页面点击出现爱心的效果 创建js文件 在/themes/next/source/js/src下新建文件clicklove.js,接着把该链接下的代码拷贝粘贴到clicklove.j ...

  4. 用PHP写一个双向队列

    PHP写一个双向队列,其实是在考察PHP几个内置数组的函数 用PHP写一个双向队列 <?php class Deque{ public $queue = array(); /** * 尾部入对 ...

  5. Codeforces - 220B Little Elephant and Array(莫队模板题)

    题意: m次查询.每次查询范围[L,R]中出现次数等于该数字的数字个数. 题解: 由于分块,在每次询问中,同一块时l至多移动根号n,从一块到另一块也是最多2倍根号n.对于r,每个块中因为同一块是按y排 ...

  6. 发现JDK的3个bug

    1.Annotation引用非空enum数组返回空数组 首次发现时的环境:JDK 1.8 首次发现所在项目:APIJSON 测试用例: public enum RequestRole { /**未登录 ...

  7. POJ 1236 Networks of School Tarjan 基础

    题目大意: 给一个有向图,一个文件可以从某个点出发传递向他能连的边 现在有两个问题 1.至少需要多少个放文件可以让整个图都有文件 2.可以进行一个操作:给一对点(u,v)连一条u->v的有向边, ...

  8. 动态规划DP的斜率优化 个人浅解 附HDU 3669 Cross the Wall

    首先要感谢叉姐的指导Orz 这一类问题的DP方程都有如下形式 dp[i] = w(i) + max/min(a(i)*b(j) + c(j)) ( 0 <= j < i ) 其中,b, c ...

  9. WKWebview 和 WebViewJavascriptBridge

    WKWebview 和 WebViewJavascriptBridge https://www.cnblogs.com/L-vincen/p/6681435.html 链接在这里,有很多不错的文章,大 ...

  10. js得到时间戳(10位数)

    //从1970年开始的毫秒数然后截取10位变成 从1970年开始的秒数 function timest() { var tmp = Date.parse( new Date() ).toString( ...