【数据结构】- 复杂度、顺序表、链表

本文深入解析了算法复杂度、线性结构(顺序表、链表)和常见操作,包括时间复杂度计算、空间复杂度分析,以及数据结构在实际项目中的运用,如B+树、红黑树等。通过实例讲解和代码重构,提升读者的理论理解和编程能力。
摘要由CSDN通过智能技术生成

https://www.bilibili.com/video/BV1xK4y1U7Dc 后(复杂度、顺序表、链表)笔记
学数据结构,也就是算法并不单纯是应付考试,应付考试我不必写那么多,主要是做一个深刻的了解,平时多练练力扣的题  做不出来也要找出规律  https://leetcode-cn.com/ 
(数据结构课本都是使用C语言作为示例)代码重构,提高后台响应速度,内存溢出,面试时我们会想到算法,工作中其实比较少使用,但不代表你不学,它类似木桶效应的短板。“ MySql 为什么索引要用 B+ 树”, 那什么是B+树,红黑树,你说不出一句话来,尽管它就是底层原理

编译工具 : Microsoft Visual Studio

课本的课后习题 也要看

额,做不出来是其次,大部分情况是看不懂题意。。。哪位大佬可以指导一下
总结一: 做题前要先画图  不容易错

算法的设计要求包括,正确性、可读性、健壮性和效率与低储存量需求。
(要改代码,尽量用接口,有问题时,不要用那个类,加个类进去)

数据结构中,从逻辑上可以把数据结构分为 线性结构和非线性结构
计算机算法指的是解决问题的有限步骤

复杂度

复杂度是用来分析程序和算法运行的时间和空间占用情况。
时间复杂度 
算法中的基本操作的执行次数,为算法的时间复杂度(时间复杂度不是计算程序运行多长时间,因为运行时间和设备上硬件有关。)

计算时间复杂度 你可以运行一下C程序知道它的运算次数

void fun(){
    int count=0;
    for(int i=0;i<N;i++){
        for(int j=0;j<N;j++){
            ++count;
         }
    }
    for(int k=0;k< 2*N ; ++k){
        ++count;
    }

    int M=10;
    while(M--){
        ++count;
    }
    print("%d\n",count);

}
F(N) = N^2 + 2*N+10
大O的渐进表示法: 只需要大概执行次数 
1、用常数1取代运行时间中的所有加法常数
2、在修改后的运行次数函数中,只保留最高阶顶
3、如果最高阶顶存在且不是1,则去除与这个项目相乘的常数,得到的就是大O阶
这里使用大O的渐进表示法后, 时间复杂度为 O(N*N)  N平方

O(1)不是只找一次  而是常数个
二分查找时间复杂度O(log2n)  ,   
最好的情况是O(1)  折半查找元素   一张纸对折   在大于中间值或小于中间值找,缩小一半的查找  
计算过程:N/2/2/2../2 =1   N= 2^X   二的X次方  X是一张纸对折次数(查找次数)此时我们要的是X, 所以 x= log\binom{N}{2}

long long Fib(size_t N){   
    return N<2 ? N : Fib(N-1)*Fib(N-2);
}
递归算法复杂度如何计算:  递归次数*每次递归函数的次数  斐波那契数列,下面画一个二叉树帮助理解

1                 fib(n)

2            fib(n-1)    fib(n-2)

4    fib(n-2) fib(n-3)   fib(n-3)  fib(n-4)

8 个fib   = 2^3

答案是 2^0 + 2^1 + 2^2+...+2^(n-1) = 2^n  - 1     即O(2^N)
测试一下Fib(100)到底要运行多久,会不会卡死,运行2的100次方 有30个0的数,我的计算机CPU目前是2.90GHz 也就是29亿次运行每秒,emem太大了等不了 运行Fib(50)吧


递归计算斐波那契数列有非常多的重复 fib(n-1)返回fib(n-2) fib(n-3)。。,其中fib(n-2)重复计算了
先定义数组,用空间换时间,时间复杂度为O(N)
#include<stdio.h>
#include<malloc.h>
long long* Fib(size_t N){   
    long long* fibArray = malloc(sizeof(long long)*N);
    fibArray[0] = 0; //N是0直接返回0
    if(N==0)
        return fibArray;
    fibArray[1] = 1;
    for(int i=0; i <= N; ++i){
        fibArray[i] = fibArray[i-1] + fibArray[i-2]
    }
    return fibArray;
}
可以直接计算出 printf("%d\n",Fib(1000));

 斐波那契数列时间复杂度为O(2^N),空间复杂度是

描述 复杂度由低到高 说明 举例
对数级别 logN 二分策略 二分查找
线性级别 N 循环 找出最大元素
线性对数级别 NlogN 归并排序
指数级别 2^N 穷举查找 检查所有子集

2^N  和  N^2  大小问题:  2^0=1    0^2=0         2^10=1024    10^2=100       

 空间复杂度
几乎不关注空间复杂度,摩尔定律:集成电路上可以容纳的晶体管数目在大约每经过18个月便会增加一倍,也就是内存每过1年半翻一倍;设备上的内存一直在变高。只有嵌入式很在意空间,设备大小手限制。
时间复杂度不计算时间,计算大概运算次数。
空间复杂度不计算空间(占用多少字节),计算大概定义的变量个数

上面的Fib(){} ,开辟了N个空间, 空间复杂度是O(N)    
 

算法复杂度  3次循环就是 N^{3}

线性

数组和链表是基础,要掌握 插入删除需要什么操作   比如说数组的移动位置链表的指针指向

线性表

线性表是N个具有相同特性的数据元素的有限序列。属于线性结构,也就是连续的一条直线,常见的线性表: 数组(顺序表),链表,栈,队列,字符串
线性表是一个有限序列,可以为空 (空表)
线性表第一个元素没有直接前驱,最后一个元素没有直接后继
存储结构有顺序存储结构链式存储结构两种,前者称为顺序表,后者称为链表。存储结构就是物理结构,在内存中的数据的地址不一定是连续的。线性表只是在逻辑结构上是线性的。物理地址连续的存储单元是顺序表。

假设线性表有n个元素,如果在第i个位置插入一个新元素,需向后移动(    ) 个元素
程序中  end=n-1   n-1>=i时   后移  ps->a[end+1] = ps->a[end];
需要后移的数量为 n-i+1


设一个链表最常用的操作是在末尾插入节点和删除尾节点,则选用(D)最省时间。 
某线性表中最常用的操作是在最后一个元素之后插入一个元素和删除第一个元素,则采用()存储方式最节省运算时间,选的答案是:带尾指针的单循环链表
 A、单链表 B、单循环链表 C、带尾指针的单循环链表 D、带头节点的双循环链表
最省时间说明要避免遍历整个链表,链表末尾操作说明是循环链表,

单链表无法得到前一个节点,删除尾节点和在链表末尾插入节点也要遍历全表
带尾指针的单向链表:插入可以,但是删除无法完成,因为p需要前移,但是单向链表无法得到前一个节点。
带尾指针的双向链表:插入和删除都很简单。
带尾指针的单向循环链表:插入很简单,删除则需要遍历整个链表,比较费时。
带头指针的双向循环链表:插入和删除都很简单。

链表与顺序表区别

  • 链表

优点: 插入和删除不需要移动其它元素,空间有效利用(扩容方便)
缺点: 大量访问操作时不如顺序存储结构   不能随机访问

  • 顺序  

优点: 1、可随机存取,存储密度高;       2、缓存利用率比较高
缺点: 1、插入或删除操作时,需大量移动元素 时间复杂度O(N)               
  2、  要求连续的内存空间,空间不够时,增容会消耗内存(可能存在空间浪费,增容有一些效率损失

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

huang_ftpjh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值