程序设计实践-阅读笔记(二)

 

 

有一段时间未读什么书了,周末两天于是拿起程序设计实践大概翻了一遍,以下便是个人总结的第二章的内容。

第二章:算法与数据结构

  对大部分程序员而言,所需要的是知道有哪些合适的、可用的算法和数据结构,知道如何在各种可以互相替代的东西之中做出选择。

2.1检索

  顺序检索非常简单,但是他的工作量与被检索数据的数目成正比。如果要找的数据并不存在,数据量加倍也会是使检索的工作量加倍。这是一种线性关系--运行时间是数据规模的线性函数,因此这种检索也被称为线性检索。

  二分检索方法效率更高一些。以下是二分检索的一个实例:

   

   typedef struct Nameval Nameval;

    struct Nameval{

    char *name;

    int value;

    };

 

 /*Value are Unicode/ISO106446 encoding.*/

  Nameval htmlchars[]={

    "AElig",0x00c6,

    "Acute",0x00c1,

    "Acirc",0x00c2,

    /*  .....  */

    "zeta",0x03b6,

  };

 /* lookup:binary search for name in tab:reurn index */

  int lookup(char *name,Nameval tab[],int ntab)

  {

    int low,high,mid,cmp;

    low = 0;

    high = ntab -1;

    while(low<=high){

      mid = (low+high)/2;

      cmp = strcmp(name,tab[mid].name);

      if(cmp<0)

        high = mid -1;

      else if(cmp>0)

        low = mid +1;

      else

        return mid; 

    }

    return -1;

  }

 

可见,项目越多,二分检索的优势也就越明显。

2.2排序

  二分检索只能用在元素已经排好序的数组上。如果事先不知道被处理的数据,那么就必须在程序运行中做排序。最好的排序算法之一是快速排序

  下面是quicksort函数做整数数组的排序:

  /* quicksort:sort v[0]..v[n-1]  into increasing order */

  void quicksort(int v[],int n)

  {

    int i,last;

    if  ( n <= 1 )

      return ;

    swap(v,0,rand() % n);

    last = 0;

    for(i = 1;i < n; i++)

      if( v[i] <v[0])

        swap(v, ++last, i);

    swap(v, 0, last);

    quicksort(v, last);

    quicksort(v+loast+1, n-last-1);

  }

   /* swap:interchange v[i] and v[j] */

  void swap(int v[],int i,int j)

  { 

    int temp;

    temp = v[i];

    v[i] = v[j];

    v[j] = temp;

  }

2.3库 

  C和C++的标准库里已包含了排序函数。他应该能够对付恶劣的输入函数,并运行的尽可能快。多年的历史证明,程序员能把二分检索程序写正确也是很不容易的。

2.4一个java快速排序  

  定义接口:

  interface Cmp{

    int cmp(Object x,Object y);

  }

  定义了对Integer类型经行比较的函数:

  //Icmp:Inter comparison

  class Icmp implements Cmp{

    public int cmp(Object o1,Object o2)

    {

      int i1 = ((Integer) o1).intValue();

      int i2 = ((Integer) o2).intValue();

      if (i1 < i2)

        return -1;

      else if (i1 == i2)

        return 0;

      else

        return 1;

    }

  }

定义了字符串的比较:

  //Scmp:String comparison

  class Scmp implements Cmp{

    String s1 = (String) o1;

    String s2 = (String) o2;

    return s1.compareTo(s2);

  }

quicksort函数实现:

  //Quicksort.sort:quicksort v[left]..v[right]

  static void sort(Object[] v, int left, int right, Cmp cmp)

  {

    int i,last;

    if(left > = right)

      return;

    swap(v, left, rand(left, right));

    last = left;

    for(i = left+1; i<=right; i++)

      if(cmp.cmp(v[i], v[left] )< 0)

        swap(v, ++last, i)

    swap(v, left, last);

    sort(v, left, last-1, cmp);

    sort(v, last+1, right, cmp);

  }

随机数由一个函数生成,它产生范围在left和right之间的随机数:

  static Random rgen = new Random();

  //Quicksort.rand:return random integer in [left, right]

  static int rand(int left, int right)

  {

    return left + Math.abs(rgen.nextInt())%(right - left + 1);

  }

最后,如果调用Quicksort.sort对一个String数组排序,如下写:

  String[] sarr = new String[n];

  // fill n elements of sarr.....

  Quicksort.sort(sarr, 0, sarr.length -1,new Scmp());

2.5大O记法

  在这种描述中使用最基本的参数是n,即问题的规模,把复杂性或运行时间表达为n的函数。

2.8树

  树是一种分层性数据结构。

  二分检索树的构建方式:在树里递归向下,根据情况确定向左或向右,直到找到了链接新节点的正确位置。节点应该正确的初始化为Nameval类型的对象,它包含一个名字,一个值和俩个空指针。新节点总是作为叶子节点加入的,他没有子节点。

  typedef struct Nameval Nameval;

  struct Nameval {

    char  *name;

    int   value;

    Nameval  *left;  /* lesser */

    Nameval  *right;  /* greater */

  }

树有插入、查找、遍历等算法。

2.9散列表

  散列表是典型应用的符号表,在一些值(数据)与动态的字符串(关键码)集合的成员间建立一种关联。在实践中,散列函数应该预先定义好,事先分配好一个适当大小的数组,这些通常在编译时完成。数组的每一个元素是一个链表,链接起具有该散列值得所有数据项。

  

 

posted @ 2016-01-20 19:53  思凡念真  阅读(212)  评论(0编辑  收藏  举报