zoukankan      html  css  js  c++  java
  • 大话数据结构笔记整理(1)

    大话数据结构笔记整理(1)

    这几天刷题遇到了瓶颈,就想着学习一波数据结构,好友推荐了《大话数据结构》,为了让自己日后来反思自己2020年7月20日是多么的蒟蒻,于是决定写一篇笔记博客。

    第一章,数据结构绪论

    • 数据:是描述客观事物的符号,是计算机中可以操作的对象,是能被计算机识别,并输入给计算机处理的符号集合。
    • 数据元素: 是组成数据的、有一定意义的基本单位,在计算机中通常作为整体处理。也被称为记录。
    • 数据项:一个数据元素可以由若干个数据项组成。数据项是数据不可分割的最小单位。
    • 数据对象:是性质相同的数据元素的集合,是数据的子集。
    • 数据结构:是相互之间存在一种或多种特定关系的数据元素的集合。

    逻辑结构与物理结构

    1. 逻辑结构:是指数据对象中数据元素之间的相互关系。分为以下4种:

    • 集合机构:集合结构中的数据元素除了同属于一个集合外,它们之间没有其他关系。各个数据元素是”平等”的,类似于数学中的集合。
    • 线性结构:线性结构中的数据元素之间是一对一的关系。
    • 树形结构:树形结构中的数据元素之间存在一种一对多的层次关系。
    • 图形结构:图形结构的数据元素是多对多的关系。

    2. 物理结构:是指数据的逻辑结构在计算机中的存储形式。

    • 顺序存储结构:是把数据元素放在地址连续的存储单元里,其数据间的逻辑关系和物理关系是一致的。
    • 链式存储结构:是把数据元素存放在任意的存储单元里,这组单元可以是连续的,也可以是不连续的。

    抽象数据类型

    数据类型:是指一组性质相同的值得集合及定义在此集合上的一些操作的总称。
    C语言中,按照取值的不同,可以分为两类:

    • 原子类型:是不可以再分解的基本类型,包括整型、实型、字符型等。
    • 结构类型:由若干个类型组合而成,是可以再分解的。例如,整型数组是由若干整型数组组成的。

    抽象数据类型(Abstract Data Type, ADT):是指一个数学模型及定义在该模型上的一组操作。抽象数据类型体现了程序设计中问题分解、抽象和信息隐藏的特性。



    第二章,算法

    算法是解决特定问题求解步骤的描述,在计算机中表现为指令的有序序列,并且每条指令表示一个或多个操作。

    算法的特性

    算法的五个基本特性:输入输出、有穷性、确定性、可行性。

    • 算法具有零个或多个输入
    • 算法至少有一个或多个输出
    • 算法在执行有限的步骤后,自动结束而不会出现无限循环,并且每一个步骤在可接受的时间内完成
    • 算法的每一步骤都具有确定的含义,不会出现二义性
    • 算法的每一步都必须是可行的,也就是说,每一步都能够通过执行有限次数完成

    算法设计的要求

    1. 正确性:算法的正确性是指算法至少应该具有输入、输出和加工处理无歧义性、能正确反映问题的需求、能够得到问题的正确答案。

      • 算法程序没有语法错误
      • 算法程序对于合法的输入数据能够产生满足要求的输出结果
      • 算法程序对于非法的输入数据能够产生满足规格说明的结果(一般情况下,将此作为判断一个算法是否正确的标准)
      • 算法程序对于精心选择的,甚至刁难的测试数据都有满足要求的输出结果
    2. 可读性:算法设计的另一个目的是为了便于阅读、理解和交流。

    3. 健壮性:当输入数据不合法时,算法也能做出相关处理,而不是产生异常或莫名其妙的结果。

    4. 时间效率高和存储量低:设计算法应该尽量满足时间效率高和存储量低的需求。

    算法效率的度量方法

    1. 事后统计方法:这种方法主要是通过设计好的测试程序和数据,利用计算机计时器对不同算法编制的程序的运行时间进行比较,从而确定算法效率的高低。
    2. 事前分析估算方法:在计算机程序编制前,依据统计方法对算法进行估算,一个程序的运行时间,依赖于算法的好坏和问题的输入规模,在分析程序的运行时间时,最重要的是把程序看成是独立于程序设计语言的算法或一系列步骤。

    函数的渐近式增长

    函数的渐近增长:给定两个函数 f(n) 和 g(n), 如果存在一个整数N,使得对于所有的 n > N, f(n) 总是比 g(n) 大,那么,我们说 f(n) 的增长渐近快于 g(n)。

    判断一个算法的效率时,函数中的常数和其他次要项常常可以忽略,而更应该关注主项(最高阶项)的阶数。

    算法时间复杂度

    在进行算法分析时,语句总的执行次数 T(n) 是关于问题规模 n 的函数,进而分析 T(n) 随 n 的变化情况并确定 T(n) 的数量级。算法的时间复杂度,也就是算法的时间度量,记作:T(n) = O(f(n))。它表示随问题规模 n 的增大,算法执行时间的增长率和 f(n) 的增长率相同,称作算法的渐近时间复杂度,简称为时间复杂度。其中 f(n) 是问题规模 n 的某个函数。

    推导大 O 阶方法

    1. 用常数 1 取代运行时间中的所有加法常数。
    2. 在修改后的运行次数函数中,只保留最高阶项。
    3. 如果最高阶存在且不是 1,则去除与这个项相乘的常数。
      得到的结果就是大 O 阶。
    • 常数阶:O(1):不管n为多少,执行的次数都是恒定的,不会随着n的变大而发生变化,其时间复杂度为O(1)
    • 线性阶:O(n):循环结构中的代码需要执行n次,其时间复杂度为O(n)。
    • 对数阶:O(logn):有多少个2相乘后大于n,则会退出循环。
    • 平方阶:O(n^2):两层循环嵌套。

    常见的时间复杂度

    算法空间复杂度

    算法的空间复杂度通过计算算法所需的存储空间实现,算法空间复杂度的计算公式记作:S(n)=O(f(n)),其中,n为问题的规模,f(n)为语句关于n所占存储空间的函数。

    当不用限定词地使用”复杂度”时,通常都是指时间复杂度



    第三章,线性结构

    线性表

    1、零个或多个数据元素的有限序列

    2、除第一个元素外,每一个元素有且只有一个直接前驱元素,除了最后一个元素外,每一个元素有且只有一个直接后继元素,数据元素之间的关系是一对一的关系。

    3、在较复杂的线性表中,一个数据元素可以由若干个数据项组成

    线性表的顺序存储结构

    线性表的顺序存储结构,指的是用一段地址连续的存储单元一次存储线性表的数据元素

    顺序存储方式

    在内存中占据一定的内存空间,然后把相同数据类型的数据元素依次存放在这块空地中

    属性:

    • 存储空间的起始位置:数组data,它的存储位置就是存储空间的存储位置
    • 线性表的最大存储容量:数组长度MaxSize
    • 线性表的当前长度:length

    存储器中的每个存储单元都有自己的编号,这个编号称为地址

    对于每个线性表位置的存入或者取出数据,对于计算机来说都是相等的时间(),也就是一个常数,因此它的时间复杂度为O(1)

    顺序存储结构的插入与删除

    插入:
    • 如果插入位置不合理,抛出异常
    • 如果线性表长度大于等于数组长度,则抛出异常或动态增加容量
    • 从最后一个元素开始向前遍历到第i个位置,分别将它们都向后移动一个位置
    • 将要插入元素填入位置i处
    • 表长加1
    删除:
    • 如果删除位置不合理,抛出异常
    • 取出删除元素
    • 从删除元素位置开始遍历到最后一个元素位置,分别将它们都向前移动一个位置
    • 表长度减1

    插入或删除时,平均移动次数和最中间的那个元素移动次数相等,为(n-1)/2

    插入和删除时,时间复杂度为O(n)

    线性表顺序存储结构的优缺点


    线性表的链式存储结构

    用一组任意的存储单元存储线性表的数据元素,这组存储单元可以是连续的,也可以是不连续的,这就意味着,这些数据元素可以存在内存未被占用的任意位置。链式结构中,除了要存储数据元素信息外,还要存储它的后继元素的存储地址。

    链表中第一个结点的存储位置叫做头指针,之后的每一个结点,其实就是上一个的后继指针指向的位置,最后一个结点的指针为null。

    为了更加方便地对链表进行操作,有时会在单链表的第一个结点前附设一个结点,称为头结点,头结点的数据域可以不存储任何信息,也可以存储如线性表的长度等附加信息,头结点的指针域存储指向第一个结点的指针。

    头指针与头结点的异同:
    • 头指针是指链表指向第一个结点的指针,若链表有头结点,则是指向头结点的指针。
    • 头指针具有标识作用,所以常用头指针冠以链表的名字。
    • 无论链表是否为空,头指针均不为空,头指针是链表的必要元素。
    • 头结点是为了操作的统一和方便而设立的,放在第一元素的结点之前,其数据域一般无意义(也可存放链表的长度)。
    • 有了头结点,对在第一元素结点前插入结点和删除第一结点,其操作与其它结点的操作就统一了。
    • 头结点不一定是链表必须要素。
    单链表的读取

    单链表中查找某一个元素,必须要从头开始找

    获得链表第i个数据的算法思路:
    • 声明一个结点p指向链表第一个结点,初始化j从1开始。
    • 当j<i时,就遍历链表,让p的指针向后移动,不断指向下一结点,j累加1。
    • 若到链表末尾p为空,则说明第i个元素不存在。
    • 否则查找成功,返回结点p的数据。

    时间复杂度为O(n)

    单链表的插入与删除
    s->next=p->next; p->next=s;
    
    单链表第i个数据插入结点的算法思路:
    删除结点
    q=p->next;   p->next=q->next;
    
    单链表第i个数据删除结点的算法思路:

    单链表在查询、插入和删除操作上的时间复杂度都是O(n),对于插入或者删除数据越频繁的操作,单链表的效率优势就越是明显。

    单链表的整表创建
    单链表整表创建的算法思路:
    • 声明一结点p和计数器变量i
    • 初始化一空链表L
    • 让L的头结点的指针指向NULL,即建立一个带头结点的单链表

    循环:

    • 生成一新结点赋值给p
    • 随机生成一数字赋值给p的数据域p->data
    • 将p插入到头结点与前一新结点之间(头插法,始终让新结点在第一的位置),也可以将p插入到终端结点的后面(尾插法)
    单链表的整表删除
    单链表整表删除的算法思路如下:
    • 声明一结点p和q
    • 将第一个结点赋值给p

    循环

    • 将下一结点赋值给q
    • 释放p
    • 将q赋值给p

    单链表结构与顺序存储结构优缺点


    静态链表

    用数组描述的链表叫做静态链表(数组中的元素由两个数据域组成,data和cur)

    数组中的第一个元素(下标为0)的cur存放备用链表的第一个结点的下标(即下一个元素插入存放的位置),数组的最后一个元素的cur则存放第一个有数值的元素的下标(即存放链头的位置)。

    静态链表的插入操作

    将元素”丙”插入到”乙”和”丁”之间

    静态链表的删除操作

    将元素”甲”删除

    静态链表优缺点

    循环链表

    将单链表中终端结点的指针端由空指针改为指向头指针,就使整个单链表形成一个环,这种头尾相接的单链表称为单循环链表,简称循环链表。

    双向链表

    双向链表是在单链表的每个结点中,再设置一个指向其前驱结点的指针域。

    非空的循环的带头结点的双向链表如下图所示:
    双向链表在插入和删除时,需要更改两个指针变量
    s->prior = p;
    s->next = p->next;
    p->next->prior = s;
    p->next = s;
    
    删除结点p,只需要下面两步骤
    p->prior->next = p->next;
    p->next->prior = p->prior;
    free(p);
    

    因为还不太会使用Typora,导致上传到博客园图片显示不了,

    导致白白辜负了自己整理图片等的几个小时,暂时就先用文字吧。

    等什么时候找到一个合适的图床网站后再说吧,看到时候想不想的起来。

    最后分享一个趣事:在家10天喝了30瓶牛奶,居然让我的肩宽、胸肌、肱二头肌等都大了一圈。————别想歪了,我是男的!

    本是青灯不归客, 却因浊酒留风尘
  • 相关阅读:
    WPF鼠标拖放功能(拖放图片,文本)
    PHP封装属性
    vs 启动时报错:未能加载文件或程序集 SharpGit
    C#.NET Winform承载WCF RESTful API (硬编码配置)
    使用edge浏览器时,怎么让alt+tab不切换他的子标签页而只在程序间切换?
    C#.NET Winform使用线程承载WCF (硬编码配置)
    AnkhSVN For Visual Studio 2022
    ASP.NET MVC 查询加分页
    C#.NET Winform承载WCF RESTful API (App.config 方式)
    C#.NET Windows服务承载WCF
  • 原文地址:https://www.cnblogs.com/wit-panda/p/13352678.html
Copyright © 2011-2022 走看看