整理学数据结构的一些笔记(一)

整理学数据结构的一些笔记(一)

一、数据结构的部分铺垫

  1. 在计算机科学中,除非有特别的的声明,所有的对数都是以2为底的。

  2. 对数的换底公式:logAB = (logcB)/(logcA)。

  3. 模运算:如果N整除A - B,那么就说A与B模N同余,记为A≡B(mod N).

    例:81≡61≡1(mod 10).

    若A≡B(mod N), 则A+C≡B+C(mod N) AD≡BD(mod N)

  4. 递归简论:当一个函数用它自己来定义时就称为是递归的。C允许函数递归。例:

    int F(int x )
                       {
                           If(x==0)
                               return 0;
                           else
                               return 2*F(x-1)
                       }
    

    C的递归函数若无基准情况,是毫无意义的。例中的基准情况即:F(0)=0.

    递归的四个基本法则:

    (1) 基准情形(base case)。你必须总要有某些基准的情形,它们不用递归就能求解。

    (2) 不断推进(making progress)。对于那些需要递归求解的情形,递归调用必须总能够朝着产生基准情形的方向推进。

    (3) 设计法则。假设所有的递归调用都能进行。

    (4)合成效益法则(compound interest rule)。在求解一个问题的同一实例时,切勿在不同的递归调用中做重复性的工作。 (尚待理解)

    ​ 数的递归打印算法( N >= 0):

     void  PrintOut( unsigned int N )
                               {  
                                   if( N >= 10)
                                       PrintOut( N / 10);
                                   PrintDigit( N % 10);
                              }      (无基准情况)
    

    二、数学基础

    1. 定义:如果存在正常数c和n0使得当N>=n0时T(N)<=cf(N),则记为T(N) =O(f(N))。即T(N)的增长率小于等于与f(N)的增长率。例如:1000N=O(N**2).这种记法称为大O记法。

    2. 定义:如果存在正常数c和n0使得当N>=n0时T(N)>=cg(N),则记为T(N) = Ω(g(N))。即T(N)的增长率大于等于g(N)的增长率。

    3. 定义:T(N)=θ(h(N))当且仅当T(N) = O(f(N))且T(N) = Ω(g(N))。即增长率大小相等。

    4. 定义:T(N) = o(f(N))当且仅当T(N) = O(f(N))且T(N) ≠ θ(h(N))。即T(N)的增长率小于与f(N)的增长率。此为小o记法。区别:没有等于。

    5. 法则1:如果T1(N) = O(f(N))且T2(N) = O(g(N)),那么

    ​ T1(N)+ T2(N) = max(O(f(N)),O(g(N)));

    ​ T1(N)* T2(N) = O(f(N)*g(N)).

    法则2:如果T(N)是一个k次多项式,则T(N) = θ(N**k).

    法则3:对任意常数k,(log N)**k = O(N).即对数增长非常缓慢。

    1. 当n趋于无穷时,对f(N)/g(N)求极限;当极限为0时,f(N) = o(g(N));当极限是∞时,g(N) = o(f(N));极限为c ≠ 0时,f(N)=θ(g(N));当极限左右摆动时,二者无关。常常舍去低阶和常数。

    2. 运行时间计算(不存在特定的时间单位):策略:从内向外。

      法则一:for循环:一次for循环的运行时间至多是该for循环内语句的运行时间乘以迭代的次数。

      法则二:嵌套的for循环。从里向外分析这些循环。在一组嵌套循环内部的一条语句总的运行时间为该语句的运行时间乘以该组所有的for循环的大小的乘积。例:

     for( i =0;i < N; i++)
    {
    	for(j=0;j

    法则三:顺序语句:将各个语句的运行时间求和即可(其中的最大值就是所谓的运行时间)。例:

    for(i=0;i

    法则四:IF/ELSE语句:

    对于程序片段:

    if(x)
    {
    	S1
    }
    else
    {
    	S2
    }//一个if/else语句的运行时间从不超过判断再加上S1和S2中运行时间长者的总的运行时间。
    

    最大子序列的一个较优算法:

    int MaxSubsequenceSum(const int A[],int N)
    {
    	int ThisSum,MaxSum,j;
    	ThisSum = MaxSum = 0;
    	for(j = 0;j < N;j++)
    	{
    		ThisSum += A[j];
    		if(ThiaSum > MaxSum)
    		{
    			MaxSum = ThisSum;
    		}
    		else if(ThisSum < 0)
    		{
    			ThisSum = 0;
    		}
    	}
    	return MaxSum;
    }//运行时间相对较短。
    
    1. 运行时间中的对数:如果一个算法用常数时间(O(1))将问题的大小削减为其中一部分(通常是1/2),那么该算法就是O(logN);如果使用常数时间只是把问题减少一个常数,那么这种算法就是O(N)的。

    2. 第一个数据结构实现方法:对分查找

    函数部分:

    int BinarySearch(const ElementType A[],ElenentType X,int N)
    {
    	int Low,Mid,High;
    	Low = 0;
    	High = N-1;
    	while(Low <= High)
    	{
    		Mid = ( Low + High) / 2;
    		if(A[Mid] < X)
    		{
    			Low = Mid + 1;
    		}
    		else if(A[Mid] > X)
    		{
    			High  = Mid + 1;
    		}
    		else 
    		   return Mid;
    	}
    	return -1;
     } //运行时间为O(logN)。
    

    10.欧几里德算法(计算两个整数的最大公因数):Gcd(M,N)  [此时M>=N,若M

    unsigned int Gcd(unsigned int M, unsigned int N)
    {
    	unsigned int Rem;
    	while( N > 0 )
    	{
    		Rem = M % N;
    		M = N;
    		N = Rem;
    	}
    	return M;
    }
    

    11.定理:如果M > N,则 M mod N < M/2.

你可能感兴趣的:(数据结构)