《数据结构》学习笔记

这篇具有很好参考价值的文章主要介绍了《数据结构》学习笔记。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.算法分析的两个主要任务:正确性(不变性 + 单调性) + 复杂度。

2.复杂度分析的主要方法:

  • 迭代:级数求和;
  • 递归:递归跟踪 + 递推方程
  • 猜测 + 验证

3.级数:

(1)算术级数:与末项平方同阶
T ( n ) = 1 + 2 + ⋯ + n = n ( n + 1 ) 2 = O ( n 2 ) T(n) = 1 + 2 + \cdots + n = \frac{n(n+1)}{2} = O(n^2) \notag T(n)=1+2++n=2n(n+1)=O(n2)
(2)幂方级数:比幂次高出一阶
∑ k = 0 n k d ≈ ∫ 0 n x d + 1 d x = 1 d + 1 x d + 1 ∣ 0 n = 1 d + 1 n d + 1 = O ( n d + 1 ) \sum \limits _{k=0} ^ n k^d \approx \int _0 ^n x^{d+1} \text{d} x = \frac{1}{d+1} x^{d+1} \bigg|_0^n = \frac{1}{d+1} n^{d+1} = O(n^{d+1}) \notag k=0nkd0nxd+1dx=d+11xd+1 0n=d+11nd+1=O(nd+1)
例如:
T 2 ( n ) = 1 2 + 2 2 + ⋯ + n 2 = n ( n + 1 ) ( 2 n + 1 ) 6 = O ( n 3 ) T 3 ( n ) = 1 3 + 2 3 + ⋯ + n 3 = n 2 ( n + 1 ) 2 4 = O ( n 4 ) T 4 ( n ) = 1 4 + 2 4 + ⋯ + n 4 = n ( n + 1 ) ( 2 n + 1 ) ( 3 n 2 + 3 n − 1 ) 30 = O ( n 5 ) \begin{aligned} & T_2(n) = 1^2 + 2 ^ 2 +\cdots + n^2 = \frac{n(n+1)(2n+1)}{6} = O(n^3) \\ & T_3(n) = 1^3 + 2 ^3 +\cdots + n^3 = \frac{n^2(n+1)^2}{4} = O(n^4) \\ & T_4(n) = 1^4 + 2^4 +\cdots + n^4 = \frac{n(n+1)(2n+1)(3n^2+3n-1)}{30} = O(n^5) \end{aligned}\notag T2(n)=12+22++n2=6n(n+1)(2n+1)=O(n3)T3(n)=13+23++n3=4n2(n+1)2=O(n4)T4(n)=14+24++n4=30n(n+1)(2n+1)(3n2+3n1)=O(n5)
(3)几何级数:与末项同阶
T a ( n ) = a 0 + a 1 + ⋯ + a n = a n + 1 − 1 a − 1 = O ( a n ) T_a(n) = a^0 + a^1+\cdots+a^n = \frac{a^{n+1}-1}{a-1} = O(a^n) \notag Ta(n)=a0+a1++an=a1an+11=O(an)
例如:
1 + 2 + 4 + ⋯ + 2 n = 2 n + 1 − 1 = O ( 2 n + 1 ) = O ( 2 n ) 1+2+4+\cdots+2^n = 2^{n+1}-1=O(2^{n+1})=O(2^n)\notag 1+2+4++2n=2n+11=O(2n+1)=O(2n)
(4)收敛级数:
1 1 × 2 + 1 2 × 3 + 1 3 × 4 + ⋯ + 1 ( n − 1 ) × n = 1 − 1 n = O ( 1 ) 1 + 1 2 2 + ⋯ + 1 n 2 < 1 + 1 2 2 + ⋯ + = π 2 6 = O ( 1 ) 1 3 + 1 7 + 1 8 + 1 15 + 1 24 + 1 26 + 1 31 + 1 35 + ⋯ = 1 = O ( 1 ) \begin{aligned} & \frac{1}{1\times 2} + \frac{1}{2 \times 3} + \frac{1}{3\times4} +\cdots +\frac{1}{(n-1)\times n} = 1-\frac 1 n = O(1) \\ & 1 + \frac{1}{2^2} + \cdots + \frac{1}{n^2} < 1 + \frac{1}{2^2} + \cdots + = \frac{\pi ^2}{6} = O(1) \\ & \frac{1}{3} + \frac{1}{7} + \frac{1}{8} + \frac{1}{15} + \frac{1}{24} + \frac{1}{26} + \frac{1}{31} + \frac{1}{35} + \cdots = 1 = O(1) \end{aligned} \notag 1×21+2×31+3×41++(n1)×n1=1n1=O(1)1+221++n21<1+221++=6π2=O(1)31+71+81+151+241+261+311+351+=1=O(1)
(5)两个重要级数:

  • 调和级数:

h ( n ) = 1 + 1 2 + 1 3 + ⋯ + 1 n = Θ ( log ⁡ n ) \begin{aligned} & h(n) = 1 + \frac{1}{2} + \frac{1}{3} + \cdots + \frac{1}{n} = \Theta(\log n) \end{aligned} \notag h(n)=1+21+31++n1=Θ(logn)

  • 对数级数:

log ⁡ 1 + log ⁡ 2 + log ⁡ 3 + ⋯ + log ⁡ n = log ⁡ ( n ! ) = Θ ( n log ⁡ n ) \log 1 + \log 2 +\log 3 + \cdots + \log n = \log (n!) = \Theta(n \log n) \notag log1+log2+log3++logn=log(n!)=Θ(nlogn)

4.一些循环的复杂度估计:

(1)循环体如下:

for (int i = 1; i < n; i <<= 1)
    for (int j = 0; j < i; j++)
        O1_Operation(i, j);

其时间复杂度的计算如下:
几何级数: 1 + 2 + 4 + ⋯ + 2 ⌊ log ⁡ 2 ( n − 1 ) ⌋ = ∑ k = 0 ⌊ log ⁡ 2 ( n − 1 ) ⌋ 2 k ( let  k = log ⁡ 2 i ) = 2 ⌈ log ⁡ 2 n ⌉ − 1 = O ( n ) \begin{aligned} \text{几何级数:} \\ & 1 + 2 + 4 + \cdots + 2^{\lfloor \log_2 (n-1) \rfloor} \\ = &\sum \limits _{k=0} ^ {\lfloor \log_2 (n-1) \rfloor} 2^k \quad (\text{let}\ k = \log_2 i) \\ = & 2^{\lceil \log _2 n \rceil} - 1 \\ = & O(n) \end{aligned} \notag 几何级数:===1+2+4++2log2(n1)⌋k=0log2(n1)⌋2k(let k=log2i)2log2n1O(n)
(2)前置知识:数列 { n ⋅ 2 n } \{n\cdot 2^n\} {n2n} 的前 n n n 项和: S n = ( n − 1 ) ⋅ 2 n + 1 + 2 S_n = (n-1)\cdot 2^{n+1}+2 Sn=(n1)2n+1+2

循环体如下:

for (int i = 0; i <= n; i++)
    for (int j = 1; j < i; j += j)
        O1_Operation(i, j);

时间复杂度的计算如下:
几何级数: ∑ k = 0 n ⌈ log ⁡ 2 i ⌉ = O ( n log ⁡ n ) ( i = 0 , 1 , 2 , 3 ∼ 4 , 5 ∼ 8 , 9 ∼ 16 , ⋯   ) =   0 + 0 + 1 + 2 × 2 + 3 × 2 2 + 4 × 2 4 + ⋯ =   ∑ k = 0 ⋯ log ⁡ n ( k × 2 k − 1 ) =   O ( log ⁡ n × 2 log ⁡ n ) \begin{aligned} \text{几何级数:} & \sum \limits _{k=0}^n {\lceil \log _2 i \rceil} = O(n \log n) \\ & (i = 0, 1, 2, 3\sim4, 5\sim 8, 9 \sim 16, \cdots) \\ = &\ 0 + 0 + 1 + 2\times 2 + 3 \times 2^2 + 4 \times 2^4 +\cdots \\ = & \ \sum _{k=0\cdots \log n} (k \times 2^{k-1}) \\ = & \ O(\log n \times 2^{\log n}) \end{aligned} \notag 几何级数:===k=0nlog2i=O(nlogn)(i=0,1,2,34,58,916,) 0+0+1+2×2+3×22+4×24+ k=0logn(k×2k1) O(logn×2logn)
5.算法正确性的证明:(以起泡排序为例)

  • 不变性:经 k k k 轮扫描交换后,最大的 k k k 个元素必然就位;
  • 单调性:经 k k k 轮扫描交换后,问题规模缩减至 n − k n-k nk
  • 正确性:经至多 n n n 趟扫描后,算法必然终止,且能给出正确解答。

6.封底估算(Back-Of-The-Envelope Calculation):

(1)1 day = 24h x 60min x 60sec ≈ \approx 25 x 4000 = 10^5 sec
(2)10^9 sec ≈ \approx 30 year

7.最长公共子序列:

(1)递归版:

unsigned int lcs(const char* A, int n, const char* B, int m)
{
    if (n < 1 || m < 1) return 0; // recursion base
    
    else if (A[n - 1] == B[m - 1]) // decrease-and-conquer
        return 1 + lcs(A, n - 1, B, m - 1);
    
    else // divide-and-conquer
        return max(lcs(A, n, B, m - 1), lcs(A, n - 1, B, m));
}

(2)迭代版:

unsigned int lcs(const char* A, int n, const char* B, int m)
{
    if (n < m)
    {
        swap(A, B);
        swap(n, m); // make sure m <= n
    }
    
    unsigned int* lcs1 = new unsigned int[m + 1];
    unsigned int* lcs2 = new unsigned int[m + 1];
    
    memset(lcs1, 0x00, sizeof(unsigned int) * (m + 1));
    lcs2[0] = 0;
    
    for (int i = 0; i < n; swap(lcs1, lcs2), i++)
        for (int j = 0; j < m; j++)
            lcs2[j + 1] = (A[i] == B[j]) ? 1 + lcs1[j] : max(lcs2[j], lcs1[j + 1]);
    
    unsigned int res = lcs1[m];
    delete [] lcs1; delete [] lcs2;
    
    return res;
}

8.总和最大区段:

(1) O ( n 3 ) O(n^3) O(n3) 蛮力算法:

int gs_BF(int A[], int n)
{
    int gs = A[0]; // current max
    
    for (int i = 0; i < n; i++)
        for (int j = i; j < n; j++) // enumerate every segment
        {
            int s = 0;
            for (int k = i; k <= j; k++) s += A[k];
            if (gs < s) gs = s;
        }
    
    return gs;
}

(2) O ( n 2 ) O(n^2) O(n2) 递增策略:

// 考查所有起点相同的区间,它们的总和之间具有相关性
int gs_IC(int A[], int n)
{
    int gs = A[0]; // current max
    
    for (int i = 0; i < n; i++)
    {
        int s = 0;
        for (int j = i; j < n; j++)
        {
            s += A[j];
            if (gs < s) gs = s;
        }
    }
    
    return gs;
}

(3) O ( n log ⁡ n ) O(n\log n) O(nlogn) 分治策略:

// 将整个区间递归地分为三部分:前缀、后缀、跨越切分线的中间部分
int gs_DC(int A[], int lo, int hi) // 注意区间是左闭右开的:[lo, hi)
{
    if (hi - lo < 2) return A[lo]; // recursion base
    
    int mi = (lo + hi) >> 1;
    
    // 寻找跨越切分线左半边的gsL
    int gsL = A[mi - 1], sL = 0, i = mi;
    while (lo < i--)
    {
        sL += A[i];
        if (gsL < sL) gsL = sL;
    }
    
    // 寻找跨越切分线右半边的gsR
    int gsR = A[mi], sR = 0, j = mi - 1;
    while (++j < hi)
    {
        sR += A[j];
        if (gsR < sR) gsR = sR;
    }
    
    return max(gsL + gsR, max(gs_DC(A, lo, mi), gs_DC(A, mi, hi)));
}

(4) O ( n ) O(n) O(n) 减治策略:文章来源地址https://www.toymoban.com/news/detail-823945.html

// 该策略基于这样一个结论:
// 记suffix(k) = A[k, hi), 其中k = max{lo<=i<hi | sum[i, hi)<=0},
// 则GS(lo, hi) = A[i, j)要么是其真后缀(k <= i < j = hi),要么与之无交(j <= k)
int gs_LS(int A[], int n) // Linear Scan: O(n)
{
    int gs = A[0], s = 0, i = n;
    while (0 < i--)
    {
        s += A[i];
        if (gs < s) gs = s;
        if (s <= 0) s = 0; // 剪除负和后缀
    }
    
    return gs;
}

到了这里,关于《数据结构》学习笔记的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【雨学习】数据结构入门---线性结构的笔记及代码实现

    数组元素类型相同,大小相等 定义:         n个节点离散分配,彼此通过指针相连,每个节点只有一个前驱节点,且只有一个后续节点         首节点前没有前驱节点,尾节点没有后续节点 专业术语:         首节点:第一个有效节点         尾节点:最后

    2024年01月23日
    浏览(55)
  • 数据结构学习笔记——二叉排序树

    查找算法中,基于树这种数据结构进行查找即为树形查找,可将其分为 二叉排序树 、 平衡二叉树 和 B树 三种树形查找方法: 二叉排序树也称为二叉查找树或二叉搜索树(注意:与二分查找的判定树不同),其中各结点值的大小关系是: 左子树根结点右子树 ,且左、右子树

    2024年02月09日
    浏览(56)
  • 区块链学习笔记(2)BTC数据结构

    1.哈希指针(hash pointers):一般的指针存储的是某个结构体在内存中的地址,哈希指针除了要保存结构体的地址外,还要保存这个结构体的哈希值。 通过哈希指针,我们不但可以找到结构体在内存中的位置,同时还可以检测出结构体的内容是否遭到了篡改。 因为我们记录了

    2023年04月16日
    浏览(56)
  • 【学习笔记】数据结构算法文档(类C语言)

    1.1.1 线性表的顺序存储表示 1.1.2 顺序表中基本操作的实现 1.1.2.1 初始化 1.1.2.2 取值 1.1.2.3 查找 1.1.2.4 插入 1.1.2.5 删除 1.1.2.6 计数 1.2.1 单链表的定义和表示 ★ 关于结点 1.2.2 单链表基本操作的实现 1.2.2.1 初始化 1.2.2.2 取值 1.2.2.3 查找 1.2.2.4 插入 1.2.2.5 删除 1.2.2.6 前插法创建单

    2024年02月07日
    浏览(44)
  • Python学习笔记(三) 数据结构与常用方法

    数据结构是计算机内部对数据按一定的结构进行排列组织的存放,以达到快速查找,提取但目的 常见的数据结构有:列表、字典、元组、集合、双端队列、区间 通过键值对key=value的形式保存元素的一种数据结构 一种不可变的数据结构,一旦创建不能添加、删除与修改 出于数

    2024年02月04日
    浏览(51)
  • Halcon学习笔记(二)数据结构、通道+XLD

    图像(Image):图像是Halco中最基本的数据结构,用于表示二维图像。它包含了图像的像素值、尺寸、颜色模式等信息。图像可以是灰度图像(单通道图像)或彩色图像(多通道图像),颜色通道可以是RGB、HSV等。图像可以通过读取文件、采集设备或者算法生成。 区域(Regi

    2024年02月22日
    浏览(35)
  • C#学习笔记--复杂数据类型、函数和结构体

    特点:多个数据变量地一个集合体,可以自己命名 种类:枚举、数组和结构体 枚举:整型常量的集合 数组:任意变量类型的顺序存储的数据集合 结构体:任意变量类型的数据组合成的数据块 枚举 : 枚举可以方便表示对象的各种状态,本质还是一种变量。 例如我们可以用

    2024年02月08日
    浏览(44)
  • 区块链技术与应用 - 学习笔记3【比特币数据结构】

    大家好,我是比特桃。 本系列笔记只专注于探讨研究区块链技术原理,不做其他违反相关规定的讨论。 区块链技术已被纳入国家十四五规划,在“加快数字发展 建设数字中国”篇章中,区块链被列为“十四五”七大数字经济重点产业之一,迎来创新发展新机遇。 经科技部批

    2024年02月09日
    浏览(46)
  • 【软考程序员学习笔记】——数据结构与算法基础

    目录  🍊一、数据结构概念和分类 🍊二、数组特点存储方式 🍊三、矩阵 特殊矩阵 非特殊矩阵 🍊四、栈和队列 🍊 五、二叉树的性质 🍊六、二叉树的遍历 (1)前序遍历(先根遍历,先序遍历) (2)中遍历(中根遍历) (3)后序遍历(后根遍历,后序遍历) 🍊七、二叉排序树 🍊八、

    2024年02月12日
    浏览(62)
  • C#学习笔记--数据结构、泛型、委托事件等进阶知识点

    ArrayList 元素类型以Object类型存储,支持增删查改的数组容器。 因而存在装箱拆箱操作,谨慎使用。 ArrayList和数组区别? ArrayList使用不用说明固定长度,数组则需要 数组存储的是指定类型的,ArrayList是Object ArrayList存在装箱拆箱,数组不存在 ArrayList数组长度用Count获取 而数组

    2024年02月08日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包