算法

算法复杂度

空间复杂度 Sn

根据算法写成的程序在执行时占用存储单元的长度。这个长度往往与输入数据的规模有关。
空间复杂度过高的算法可能导致使用的内存超限,造成程序非正常中断。

时间复杂度 Tn

根据算法写成的程序在执行时耗费的时间长度。这个长度往往也与数据数据的规模有关。
时间复杂度过高的低效算法可能导致我们在有生之年都等不到运行结果。

分析一般算法的效率时,会关注下面两种复杂度:

  1. 最坏情况复杂度 Tworst(n)
  2. 平均复杂度 Tavg(n)

复杂度的渐进表示法

  • 复杂度的上界:T(n)=O(f(n)) 表示存在常数 C>0, n0>0 使得当 n>=n0 时有 T(n)<=C·f(n)
  • 复杂度的下界:T(n)=Ω(g(n)) 表示存在常数 C>0, n0>0 使得当 n>=n0 时有 T(n)>=C·g(n)
  • 当上界等于下界时:T(n)=θ(g(n)) 表示同时有 T(n)=O(h(n)) 和 T(n)=Ω(h(n))

分析复杂度的小窍门

  1. 若两段算法分别有复杂度 T1(n)=O(f1(n)) 和 T2(n)=O(f2(n)), 则:
  • 两段算法并列:T1(n)+T2(n)=max(O(f1(n)), O(f2(n)))
  • 两段算法嵌套:T1(n)xT2(n)=O(f1(n)xf2(n))
  1. 若T(n)是关于n的k阶多项式,那么 T(n)=θ(nk)
  2. 一个for循环的时间复杂度等于循环次数乘以循环体代码的复杂度
  3. if-else 结构的复杂度取决于if的条件判断复杂度和两个分支部分的复杂度,总体复杂度取三者中最大。

线性表

概念:由同类型数据元素构成有序数列的线性结构。

  • 表中元素个数称为线性表的长度
  • 线性表没有元素时,称为空表
  • 表起始位置称为表头,表结束位置称为表尾

线性表的抽象数据类型描述

类型名称:线性表(List)

数据对象集:线性表是n(>=0)个元素构成的有序序列(a1, a2, ..., an)

操作集:线性表L∈List,整数i表示位置,元素X∈ElementType

线性表的基本操作有:

  1. List MakeEmpty(): 初始化一个空线性表L;
  2. ElementType FindKth(int K, List L): 根据位序K,返回相应的元素;
  3. Int Find(ElementType X, List L): 在线性表L中查找X的第一次出现位置;
  4. void Insert(ElementType X, int i, List L): 在位序i前插入一个新元素X;
  5. void Delete(int i, List L): 删除指定位序;
  6. int Length(List L): 返回线性表L的长度n。

线性表的链式存储实现

不要求逻辑上相邻的两个元素物理上也相邻,通过“链”建立起数据元素之间的逻辑关系。

插入、删除不需要移动数据元素,只需要修改“链”

  1. 建立链表:
typedef struct LNode *List;
struct LNode {
    ElementType Data;
    List Next;
};
struct Lnode, L;
List PtrL;
  1. 求表长
int Length(List, PtrL) {
    List p = PtrL;
    int j = 0;
    while (p) {
        p = p->Next;
        j++;
    }
    return j;
}
  1. 查找
// (1) 按序号查找:FindKth
List FindKth(int K, List PtrL) {
    List p = Ptrl;
    int i = 1;
    while (p != NULL && i < K) {
        p = p->Next
        i++;
    }
    // 找到第K个,返回指针
    if (i == K) return p;
    // 否则返回空
    else return NULL;
}
posted @ 2021-09-10 18:01  wuyve  阅读(40)  评论(0)    收藏  举报