数据结构笔记

数据结构概述

  • 我们如何把现实中大量而复杂的问题以特定的数据类型和特定的存储结构保存到主存储器(内存)中,以及在此基础上为实现某个功能(比如查找某个元素,删除某个元素,对所有元素进行排序)而执行的相应操作,这个相应的操作也叫算法。
  • 数据结构=个体的存储+个体的关系存储

  • 算法=对存储数据的操作

    算法->解题的方法和步骤

衡量算法的标准

1)时间复杂度:大概程序执行的次数,而非执行的时间
详见:算法复杂度
2)空间复杂度:算法执行过程中大概所占用的最大内存
3)难易程度(主要是应用方面看重)
4)健壮性(不能别人给一个非法的输入就挂掉)

程序 = 数据的存储 + 数据的操作 + 可以被计算机执行的语言

指针

指针的重要性:
指针是 C 语言的灵魂
地址:
地址就是内存单元的编号,从 0 开始的非负整数,范围:0-FFFFFFFF【0-4G-1】
CPU=地址线,控制线,数据线=内存
指针:

  • 指针就是地址,地址就是指针。
  • 指针变量是存放内存单元地址的变量。
  • 指针的本质是一个操作受限的非负整数。只能减,不能加乘除 指针减法以及比较运算

分类:

  1. 基本类型的指针
  2. 指针和数组的关系

变量并不一定连续分配,随机分配内存。
内存:
内存是多字节组成的线性一维存储空间。
内存的基本划分单位是字节。
每个字节含有 8 位,每一位存放 1 个 0 或 1 个 1.
内存和编号是一一对应的。

软件在运行前需要向操作系统申请存储空间。在软件运行期间,该软件所占空间不再分配给其他软件。当软件运行完毕后,操作系统将回收该内存空间(操作系统并不清空该内存空间中遗留下来的数据)。

NOTE:
1)指针变量也是变量,普通变量前不能加 \ ,常量和表达式前不能加 &
2)局部变量只在本函数内部使用。
如何通过被调函数修改主调函数中普通变量的值。
1)实参为相关变量的地址;
2)形参为以该变量的类型为类型的指针变量;
3)在被调函数中通过形参变量名的形式就可以修改主函数。

头指针、头结点、首节点

参考链接
参考链接
头指针——链表头部的指针,一般默认指向头结点,若无头结点,指向第一个元素结点
头结点——链表头部第一个结点,不存储数据信息,指向第一个元素结点
首元结点——存储第一个元素的结点

头指针是指向链表中第一个结点的指针。首元结点是指链表中存储第一个数据元素的结点。头结点是在首元结点之前附设的一个结点,该结点不存储数据元素,其指针域指向首元结点,其作用主要是为了方便对链表的操作。它可以对空表、非空表以及首元结点的操作进行统一处理。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-laNB2zRY-1630458799270)(index_files/21037281.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-83kuxAcf-1630458799272)(index_files/20744140.png)]

  • 头指针具有标识作用,故常用头指针冠以链表的名字。
  • 头结点是为了操作的统一与方便而设立的,放在第一个元素结点之前,其数据域一般无意义(当然有些情况下也可存放链表的长度、用做监视哨等等)。

数据结构的研究内容

● 数据结构是一门研究非数值计算 的程序设计中计算机的操作对象以及它们之间的关系和操作的学科

● 程序 = 数据结构与算法 在这里插入图片描述 在这里插入图片描述
在这里插入图片描述

● 特点:数据元素间的关系简单,计算复杂

基本概念和术语

● 数据(Date)

能输入计算机且能被计算机处理的各种符号的集合

● 数值型

● 非数值型

● 数据元素(Date element)

数据的基本单位 集合中的个体

● 数据项

构成数据元素的最小单位

● 数据对象

性质相同的数据元素的集合 集合的子集

● 数据由数据元素组成,数据元素又是由数据项组成

eg.学生表<-个人记录<-学号姓名

● 数据结构(Data Structure)是相互之间存在一种或多种特定关系的数据元素的集合。换句话说,数据结构是带”结构"的数据元素的集合,“结构”就是指数据元素之间存在的关系。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OtGMJrcj-1630458196169)(index_files/e66e43c8abfaaa3505529d013ecb9ab1.png)]
● 逻辑结构与物理结构
https://blog.csdn.net/liu17234050/article/details/104251163
https://www.cnblogs.com/zhangshimin/articles/5617592.html
逻辑结构
0.线性结构(一对一)与非线性结构(一对多)
常用的线性结构有:线性表,栈,队列,双队列,串(一维数组)

非线性:数、图
1.集合、线性、数、图
储存结构
https://blog.csdn.net/liu17234050/article/details/104251282
顺序结构
顺序存储结构是把数据元素存放在连续的存储单元里,数据元素之间的逻辑关系是通过数据元素的位置。(在前面的数据元素就存在前面;在后面的数据元素就存在后面)C语言用数组来实现顺序存储结构
链式结构
用一组任意的存储单元存储数据元素(可能连续也可能不连续),数据元素之间的逻辑关系用指针来表示(用指针存放后继元素的存储地址)
C语言中用指针来实现链式存储结构(链表)
索引结构
在存储节点信息的同时,还建立附加索引
索引表中的每一项称为一个索引项,
索引项的一般形式是:(关键字,地址)
关键字是能唯一标识一个结点的那些数据项。
若每个结点在索引表中都有一个索引项,则该索引表称之为稠密索引(Dense Index)。若一组结点在索引表中只对应一个索引项,则该索引表称之为稀疏索引(Sparse Index)。
散列结构
https://zhuanlan.zhihu.com/p/35250419
散列存储,又称hash存储,是一种力图将数据元素的存储位置与关键码之间建立确定对应关系的查找技术

基本思想是:由节点的关键码值决定节点的存储地址。散列技术除了可以用于查找外,还可以用于存储。
数据类型

在使用高级程序设计语言编写程序时,必须对程序中出现的每个变量、常量或表达式、C语言中函数的参数、返回值,明确说明它们所属的数据类型。

C语言中:提供int,char,float,double等基本数据类型;数组、结构、共用体、枚举等构造数据类型;还有指针、空(void)类型,用户也可用typedef自己定义数据类型。

而另一些常用的数据结构,如栈、队列、树、图等,不能直接用数据类型来表示。
在C语言中,数据类型可以分为两类:

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

树的定义

在这里插入图片描述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G3if2uWW-1630458352849)(index_files/_u622A_u56FE2021_u5E7403_u670811615882773637.png)]

  • 树是N个节点的有限级
  • 其实也是一种递归的实现,即树的定义之中还用到了树的概念(套娃)
  • ps:子树之间一定是互不相交的
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YPfnvkLc-1630458352851)(index_files/_u622A_u56FE2021_u5E7403_u670811615883069786.png)]

树的基本术语

  • 结点(节点):数据元素以及指向子树的分支
  • (Degree)的概念:结点的度就是结点的孩子数,树的度就是所有结点的度的最大值(不是求和)。
  • 度为0的结点称为叶节点终端结点,度不为0的结点,称为分支结点,分支结点中除了根节点,其他结点也称为内部节点。
  • 结点的子树的根称为该结点的孩子(Child),相应地,该结点称为孩子的双亲。同一个双亲的孩子之间互称为兄弟(Sibling)。结点的祖先是从根到该结点所经分支上的所有结点。
  • 双亲不同但双亲在同一层的节点被称为堂兄弟
  • 如果将树中结点的子树看成从左至右是有次序的,不能互换的,则该树称为有序树,否则称为无序树
  • 深林是m(m>0)棵互不相交的树的集合。对树中每个结点而言,其子树的集合即为深林。
  • 树的深度(高度)即为树的层数
  • 森林是m课树的集合
  • 树一定是森林——只有一棵树的森林,但森林不一定是树。
  • 树是一种特殊的图

二叉树的定义

二叉树是结点有限,区分左右子树的有序树❌二叉树不是树的特殊情况,树与二叉树的区别在于二叉树是有序的。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yrIJArxE-1630458352853)(index_files/_u622A_u56FE2021_u5E7403_u670811615899720985.png)]

  • 每个节点最多两个孩子——二叉树中不存在大于二的节点,可以是两颗子树,也可以是一颗或者没有子树。
  • 左子树和右子树有顺序,次序不能任意颠倒。
  • 即使树中某结点只有一棵子树,也要区分是左子树还是右子树。
  • 二叉树的分类
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JSVAc8Ci-1630458352854)(index_files/f7865c08-4016-45d3-891d-022792e9fdc0.png)]
  • 二叉树的五种基本形态:
  • 空二叉树

  • 只有一个根结点

  • 根结点只有左子树

  • 根结点只有右子树

  • 根结点既有左子树又有右子树

  • 特殊二叉树:

  • 斜树
    所有结点都只有左子树的二叉树称为左斜树,所有结点都有右子树的二叉树称为右斜树。斜树的结点数即为该树的深度。

  • 满二叉树
    一颗二叉树中,所有分支的结点都存在左子树和右子树,并且所有的叶子都在同一层上,这样的二叉树称为满二叉树。
    满二叉树特点
    叶子只能出现在最下一层
    非叶子的结点的度一定是2 同样深度的树中,满二叉树的结点个数最多,叶子数最多。

  • 完全二叉树
    对一颗n各结点的二叉树按层序编号,若编号为i的结点与对应深度的满二叉树中的编号一致,则这样的二叉树称为完全二叉树。即满二叉树一定是完全二叉树,而完全二叉树不一定是满二叉树。完全二叉树是满二叉树的子集。
    完全二叉树特点
    叶子结点只能是最下两层
    最下层的叶子一定集中在左部连续位置
    倒数第二层,若有叶子结点,一定都在右部连续位置
    如果结点的度为1,该结点只有左孩子,不存在只有右子树的情况
    同样结点数的二叉树,完全二叉树的深度最小

  • 二叉树的性质

  • 在二叉树的第i层上至多有2^(i-1)个结点

  • 在深度为k的二叉树中,结点数最多为2^k - 1

  • 对于任何一个二叉树,终端结点数N0=N2+1(N2:度为2的结点)
    结点总数:N=N0+N1+N2
    连线总数=N-1(入线角度来算根结点没有入线)=2N2+N1(出线角度来算)
    对于完全二叉树,N0=[(N+1)/2]

  • 对于一颗完全二叉树,树的深度值为[log2N]+1 (N为结点数,[]为不大于该值的最大整数)

  • 对于一颗有n个结点的完全二叉树(深度为[log2N]+1)的结点按层序编号,对于任一结点i:
    1.若i=1,则结点i为根结点,无双亲;若i>1,双亲结点的编号为[i/2]
    2.若2i>n,则结点无左孩子,否则左孩子结点为2i
    3.若2i+1>n,则结点无右孩子,否则右孩子结点为2i+1
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KBwQiTbI-1630458352855)(index_files/89544593.png)]

二叉树的性质和储存结构

  • 树的抽象数据类型
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8rUo2xN8-1630458352856)(https://camo.githubusercontent.com/3d1b97f79bc1587acc9ce8d5ac74f60b91b33cad/68747470733a2f2f692e696d6775722e636f6d2f615a55586268712e7

循环链表

参考链接

  • 循环链表和单链表在判断是否为空链表的上有区别:原来判断p-> next是否为null,现在判断p->next是否为head
  • 可以有表头也可以没有(若有表头最后的单元就指向它),并且还可以是双向链表。 --黑皮书《数据结构与算法分析》

  • 优点:从表中任一结点出发均可找到表中其他结点。
  • 尾指针的使用
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QhgbwJtE-1630458578696)(index_files/_u622A_u56FE2021_u5E7403_u67081.png)]

  • 两指针的合并
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SIPm5wgF-1630458578698)(index_files/_u622A_u56FE2021_u5E7403_u670811615725978580.png)]

静态链表(链表的游标实现)

参考链接

静态链表是借助数组来描述线性表的链式存储结构,结点也有数据域data和指针域next,与前面所讲的链表中的指针不同的是,这里的指针是结点的相对地址(数组下标),又称为游标。和顺序表一样,静态链表也要预先分配一块连续的内存空间。
通过 “数组+游标” 的方式存储具有线性关系数据的存储结构就是静态链表。

我理解的就是结构体数组+单链表

eg.

typedef struct
{
    int data;
    int cur;
}StaticLinkList[MAXSIZE];

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sveK1yrS-1630458631716)(index_files/_u622A_u56FE2021_u5E7403_u670811615713739681.png)]

使用静态链表存储数据,需要预先申请足够大的一整块内存空间,也就是说,静态链表存储数据元素的个数从其创建的那一刻就已经确定,后期无法更改。

注意:

  1. 我们对第一个和最后一个元素进行特殊处理,它们的data不存放数据。
  2. 我们通常把为使用的数组元素称为备用链表。
  3. 数组的第一个元素,即下标为0的那个元素的cur存放备用链表第一个结点的下标地址。
  4. 数组的最后一个元素,即下标为MAXSIZE-1的那个元素的cur存放第一个有数值的元素的下标,相当于单链表的头结点作用。
  5. 数组的最后一个已使用的结点的游标为0.

弹幕:静态链表的存在是为了满足非C的其他没有指针的语言

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值