关于数据结构

day01

数据结构与算法

数据结构是为算法服务的

  • 算法是解决问题的思路和方法,是独立存在的

算法有三个特征:

  1. 必须要有一个结果
  2. 有穷性
  3. 可行性

两种基本的算法设计模型

  • 贪心法  贪婪算法
  • 枚举法:必须找到一个最优解  

伪代码:就是用来解决问题的思路

  • 包括:你的自然语言  数学表达形式  不纠结与你的具体编程语言形式

算法分析:

  • 任何算法的实施必定消耗时间和空间上的资源

时间复杂度:

  • 最坏时间复杂度,最优时间复杂度,平均时间复杂度

面试题:

  • 如果 a+b+c = 1000,并且a^2 + b^2 = c^2 (a,b,c都是自然数),求a,b,c的组合有哪些
    解析:
    一般算法:
    import time
    start_time=time.time()
    for a in range(1,1001):
        for b in range(1, 1001):
            for c in range(0, 1001):
                if a+b+c==1000 and a**2+b**2==c**2:
                    print(a,b,c)
    end_time=time.time()
    print('time:%d'%(end_time-start_time))
    print('结束')
    
    
    减少遍历次数节省时间算法:
    import time
    start_time=time.time()
    for a in range(1,1001):
        for b in range(1, 1001):
            c = 1000-a-b
            if a**2+b**2==c**2:
                print(a,b,c)
    end_time=time.time()
    print('time:%d'%(end_time-start_time))
    print('结束')
  • a = (0,n) b(0,n) c(0,n)
  • 0(n) = n*n*n*2
  • 0(n) = n*n*n*7
  • 最终的时间复杂度和你的规模n有关系

时间复杂度的几条基本计算规则

  • 只有常数项,时间复杂度表示为0(1)
  • 顺序结构,时间复杂度按加法计算
  • 循环结构,按乘法计算
  • 分支结构,取最大值
    只关注操作数的最高次项,其他次要项和常数项不考虑

 3                                O(1)
 2n+3                         O(n)
 3n**2+2n+3              O(n**2)
 5log2N                      O(logn)
 2n+3nlog2n+19        O(nlogn)
 6n**3+2n**2+3n+2   O(n**3)
 2**n                          O(2**n)

O(1)<O(logN)<O(n)<O(nlogn)<O(N**2)<O(N**3)<O(2**N)<O(N!)<O(N**N)
 


day02

链表

  • 二元组(元素域 elem 链接域 next)

为了掌握一个单链表,只需要用一个变量来保存这个表的首结点应用

  • (表头指针,表头变量) p表示

class Node (object):
    def __init__(self,item):
        #存储数据元素
        self.item = item:
        #链接域存储下个结点的位置信息
        self.next = None

创建空链表

删除链表:

加入元素:头部插入,一般性插入

删除元素:删除表头结点 删除其他结点

Josephus 问题

假设有n个人围坐在一起,现在要求从k个人开始报数,报n个数,报到的人自动退出,从下一个人重新开始报数,按照同样的规则来进行,直至所有人全部退出,要求按顺序输出各出列人的编号

基本的算法思路

  1. 建立一个包含n个人的编号的表
  2. 找到第k个人,从那里开始
  3.  

     

def josephus_A(n,k,m):
#给人员编号
    people = list(range(1,n+1))
    i = k-1
    #循环操作
    for num in range(n):
        #为了计数
        count = 0
        while count < m:
            if people[i] > 0:
                count +=1
            if count ==m:
                print(people[i],end="")
                people[i] = 0
            i = (i+1)%n

        if num <n-1:
            print(", ",end="")

        else:
            print("")
    return

josephus_A(41,1,3)

day03

数据结构
一.课前准备

  1. 数据:所有能被记录到计算机中并且能被计算机处理的符号的集合.
  2. 数据类型:数,字符串 ...
  3. 数据结构:计算机存储和组织数据的方式.
  4. 算法:计算机为解决特定的问题而产生的一系列解决问题的指令,简而言之,就是解决方案的准备完整的描述

二.目标

  • 数据结构:理解逻辑结构,物理结构
  • 算法:排序算法,查找算法

三.正文

逻辑结构:

  • 概念:       数据之间(与计算机无关)的关系
  • 主要分类:线性结构和非线性结构
                      其中非线性结构包括:
                      集合结构,树状结构,网状结构

     
    1. A.线性结构的特点
      1. 结构中必须存在唯一的首元素
      2. 结构中必须存在唯一的尾元素
      3. 除首元素外,结构中每一个元素有且只有一个前驱元素
      4. 除尾元素外,结构中每一个元素有且只有一个后继元素
    2. B.集合结构的特点:
      1. 无序性
      2. 互异性
      3. 确定性
    3. C.树状结构的特点
      1. 结构中必须存在唯一的一个根节点(根元素)
      2. 除根元素外,结构中每一个元素有且只有一个前驱元素
      3. 除叶元素外,结构中每一个元素拥有一个或多个后续元素
        树状结构中的数据具有一对多的父子关系
    4. D.网状结构的特点
      1. 结构中每一个元素都可以拥有任意数量的前驱元素和后继元素
      2. 结构中任意两个元素之间都可以建立互联
        网状结构中的数据具有多不多的交叉映射关系

物理结构:

  • 概念:数据具体在计算机内存中的存储方式.
  • 分类:顺序存储结构,链式存储结构

    详细介绍:
  1. 顺序存储
    是将逻辑上相邻的元素放在物理内存也是相邻的存储单元中
    优点:
    1)节省存储空间,只需要为每个数据本身分配存储空间,不需要占用额外的空间来表示元素间的逻辑关系
    2)方便随机存取元素
    缺点:
    1)连续的存储会降低空间的使用率
    2)任意位置增加或者删除数据时操作复杂
  2. 链式存储
    是使用不连续的存储空间来存放结构中的数据,将每个元素构造一个节点,节点中除了存放元素本身外,还需要存放下一个节点的地址
    优点:
    1)提高空间的使用率
    2)任意位置增加或者删除数据时操作方便
    缺点:
    1)总体的空间开销比顺序存储要大
    2)不方便随机的存取元素


    数据源:ABCDEF...
    内存中顺序:ABCDEF...

两者间关系:

  • 每一种逻辑结构采用哪种物理结构来实现是没有规定.
    所以,
    基于顺序存储实现的表结构:顺序表
    基于链式存储实现的表结构:链表

三.实战

  1. 顺序表
    动态开辟内存空间
  2. 链表
    1. 基本特征
      1. 每一个数据放在一个独立的存储区
      2. 还需保证结构中任一结点可以找到与其相关联的下一结点
      3. 前一节点用链接方式显示的记录下一个节点之间的关联
    2. 基本两种形式
      1. 单链表:即单向链表
        1. 其每个节点包含数据元素
        2. 每个结点保存指向下一结点的链接
        3. 链表的尾节点的链接域为空,None
      2. 双链表:
        1. 其每个节点包含数据元素
        2. 每个结点保存指向下一结点的链接
        3. 每个结点保存指向前一结点的链接
        4. 链表的首节点的上一结点链接域为空,None
        5. 链表的尾节点的下一结点链接域为空,None

四.容器



  1. 基本特征:
    1. 只能在一端增加和删除元素,这一端称为栈顶,另一端称为栈底
    2. 两个基本操作压人数据push 和弹出pop,弹出数据相当于删除最后插入的数据,也就是说栈实现的是一种 后进先出 的运算方式
    3. 从空栈中弹出数据和向满栈压入数据都视为一种错误

      具体实现
      1. 基于顺序存储的栈实现
      2. 基于链式存储的栈实现
  2. 队列
    基本特征:
    1. 队列可以两端增删数据,增加元素的一端称为后端,删除数据的一端称为前端
    2. 队列的基本操作同样是压人数据和弹出数据,前者相当于插入数据,后者则是删除最后先插入的数据,也就形成了 先进先出 的运算规则
    3. 在空队列中弹出数据和在满队列压入数据都视为一种错误
    4. 通常最先和最后插入的元素分别称为队首和队尾来被外界访问

      具体实现
      1. 基于顺序存储的队列实现
      2. 基于链式存储的队列实现
        使用链式存储的队列没有实质上的技术困难,但是链式结构在两端进行操作需要消耗较长时间,并不适合队列的实现。

五.二叉树

  • 二叉树是一种最简单的树状结构,其特点:
  1. 树中每个结点最多关联两个后继结点,也就是说,一个结点关联的结点数可为1 / 2 / 0.
  2. 每个结点关联的后继结点明确的分为左关联结点和右关联结点
  • 基本概念
  1. 叶结点:二叉树中没有子节点的称为树叶,即叶结点
  2. 分支结点:树种除了叶结点外其余结点均为分支结点,其有一个或者两个分支
  3. 父结点:二叉树中根节点称为该树的节点
  4. 子节点:相应的,子树的根节点就是二叉树的子节点
  5. 满二叉树:每一层结点达到最大值,所有分支结点都有左右两个分支
  6. 完全二叉树:除了最下层的节点都达到最大值,且最下层的节点都连续集中在左侧

六.算法

  • 查找算法
  1. 顺序查找
      基本思路:从第一个元素开始,逐个与要查找的元素进行对比,若比较到两者的值相同时,则返回找到的元素下标值:若没有找到,则返回-1
      评价:
        若数据量较大时,查找长度变大,效率低
        顺序查找对于数据的有序性没有要求.
  2. 二分查找
      a.二分查找也称为折半查找,属于有序查找的算法.
      b.基本思路:用给定要查找的数据与中间数据进行对比,若相等则查找成功,若不相等,根据key 与中间数据的比较结果在其左子表或者右子表中继续递归查找,直到找到或者表中无该数据为止
      c.评价:
        要求数据必须是有序的,如无序数据,先排序后使用
        因为二分查找每次将查找范围减少一半,缩短时间,
        其时间复杂度是对数级,空间复杂度为常数级
  • 排序算法
  1. 冒泡排序
    基本思路:
    1. 相邻元素俩俩相比,前者大于后者则交换
    2. 第一次遍历,从第一对数据到最后一对数据,将最大值上浮到顶端
    3. 后面继续将未排序的部分重复上步骤,依次上浮次最大值
    4. 每次扫描元素越来越少,直到不再发生交换为止
      评价:
      时间复杂度O(n2),空间复杂度O(1)
      冒泡排序算法对于数据本身的有序性非常铭感
  2. 插入排序
    基本思路:
    1. 首元素自然有序
    2. 取出下一个元素,对已排序的序列从后向前扫描
    3. 若扫描的有序数据大于被取出的元素,则该有序数据后移
    4. 若扫描的有序数据小于被取出的元素,在该有序数据后面插入被取出的元素
    5. 若扫描的所有有序数据都大于被取出的元素,则在有序数据的头部插入被取出的元素
    6. 再取出下一个元素,继续重复之前的步骤,直到所有元素都有序为止
      评价:时间复杂度:O(n2) 空间复杂度O(1)
  3. 快速排序
    算法描述:
    1. 从待排序的序列中任意选择一个基准
    2. 将所有小于基准的元素,等于基准所有元素,大于基准的元素进行分组,小于部分放前面,大于部分放后面
    3. 再以递归的方式,对基准之前和基准之后的分组继续上操作,直到每个组内的元素不多于一个为止
      评价:
      时间复杂度:O(nlogn)
      若每次都能均匀分组则,快速排序速度是最快的.

所有示例

  

猜你喜欢

转载自blog.csdn.net/qq_42584444/article/details/83063299