c语言之数据结构学习心得

2023-11-19

写在前面
  你们好,我是小庄。很高兴能和你们一起学习c语言。如果您对编程感兴趣的话可关注我的动态.
  写博文是一种习惯,在这过程中能够梳理知识和巩固知识点。

一、绪论

1、什么是数据、数据元素、数据项、数据对象、数据结构?

(1)、数据

客观事物的符号表示,指所有能输入到计算机并被计算机程序处理的符号的总称。如:数字、字符、图形、声音、动画等特殊编码定义后的数据。

(2)、数据元素

数据的基本单位,在计算机中通常作为一个整体进行考虑和处理,数据元素用于完整的描述一个对象。如:一个学生记录,树中棋盘的一个格局状态,图中的一个顶点等。

(3)、数据项

组成数据元素的、有独立含义的、不可分割的最小单位。如:学生信息表中的学号、姓名、性别都是数据项。

(4)、数据对象

性质相同的数据元素的集合,是数据的一个子集。如整数数据对象{1,2,3,4···},学生基本信息表也可以是一个对象。

(5)、数据结构

相互之间存在一种或多种特定关系的数据元素的集合。数据结构是带“结构”的数据元素的集合,“结构”是数据元素之间的关系。

2、数据结构的存储

(1)、物理结构

a、顺序存储 b、链式存储 c、索引存储、d、散列存储

(2)、逻辑结构

a、集合结构 b、线性结构 c、树形结构 d、图形结构

3、抽象数据类型

由用户定义的,表示应用问题的数据模型,以及定义在这个模型上的一组操作的总称,包括:数据对象,数据对象上关系上的集合,对数据对象的基本操作的集合。

4、算法和算法分析

(1)、含义

算法是对特定问题求解步骤的一种描述,它是指令的有限序列,其中每一条指令表示一个或多个操作。

(2)、算法的五个特征

a、有穷性 b、确定性 c、可行性(有效性) d、零个或多个输入 e、一个或多个输出

(3)、算法设计要求

a、正确性 b、可读性 c、健壮性 d、效率与低存储量需求

(4)、算法实现的三要素

a、数据 b、运算 c、控制

二、表

1、表的概念

表是由n个同一类型的元素a(1),a(2),a(3)···,a(n)组成的有限序列

2、表的逻辑特征

(1)、非空的表有且仅有一个开始元素,该元素没有前驱,而有一个后继;

(2)、有且仅有一个结束元素,结束元素没有后继,而有一个前驱;

(3)、其余的元素都有一个前驱和一个后继。

(4)、表是一种线性结构

3、存储结构

(1)、顺序存储结构 -> 数组实现表

(2)、链式存储结构 -> 链表实现表

4、实现表

(1)、用数组实现表

优点:

a、随机访问性强

b、查找速度快

缺点:

a、插入和删除效率低

b、可能浪费内存

c、内存空间要求高,必须有足够的连续内存空间

d、数组大小固定,不能动态拓展

(2)、链表实现表

优点:

a、插入删除速度快

b、内存利用率高,不会浪费内存

c、大小没有固定,拓展很灵活

缺点:

a、不能随机查找,必须从第一个开始遍历,查找效率低

5、循环链表特点

最后元素的指针指向表首,实现一个环。判断一次循环使用模(%)运算

6、双链表特点

增加一个前驱空间,使用左右指针的方式表示前后驱。

三、栈

1、栈的特点

先进后出,类似放碟子和取碟子的一个过程

2、数组实现栈

入栈:先判断栈是否满了,否则出现上溢;

出栈:先判断栈是否为空,否则出现下溢。

数据元素:top(栈顶);maxtop(栈空间);StackItem *data(存储栈元素的数组)。//typedef int StackItem;StackItem表示int类型

3、链表实现栈

数据元素:StackItem element(栈元素);typedef struct snode *slink; slink next;(下一个指针)

push(入栈)、pop(出栈),入栈和出栈都在链尾操作

四、队列

1、队列的特点

先进先出,类似正常的排队,先排先出,删除操作只能在链首,插入操作只能在链尾

2、链表实现队列

类似单链表的操作,只是比较特殊,删除操作只能在链首,插入操作只能在链尾

3、循环数组实现队列

实现思路:在删除操作不需要移动后面的元素,空出一个空间用于判断是否到最后一个元素

五、排序与选择算法

1、简单排序

(1)、冒泡排序

时间复杂度为O(n2)

思路:使用一个临时变量,前后两两比较,进行排序

(2)、插入排序

时间复杂度为O(n2)

思路:使用一个新的空数组,逐个遍历一个无序数组,然后逐个比较插入到新的空数组。

(3)、选择排序

时间复杂度为O(n2)

思路:假设第一个元素下标为最小,遍历所有元素,如果比这个元素小则交换值,下标进行加一,继续比较,直到最后一个元素下标不进行比较。

2、快速排序

时间复杂度为O(nlogn)

思路:选择一个基准元素,选择一个左区间和右区间。把大的放左边,小的放右边(或者相反),使用递归的方式进行排序。关键是确定基准点

(2)、非递归快速排序

使用栈的方式进行排序,最坏情况只耗费logn栈空间典型的用空间换时间

3、合并排序

时间复杂度为O(nlogn)

思路:先分成若干个两个单位排序,然后不断左右合并排序,最终排序完成

4、计数排序

前提:必须知道待排序序列中所有元素的范围,min~max,这样才能构造一个数组

时间复杂度为O(n)

思路:设置一个数组存放排序的结果,设置一个辅助数组用于对输入的元素进行计数,然后根据下标输出对应计数的个数(不为0的个数)

5、桶排序

前提:必须知道待排序序列中所有元素的范围,min~max,这样才能构造一个数组

时间复杂度为O(n)

桶排序是在计数排序的基础上衍生的

思路:把一个长度分为多个桶,在每个桶里面进行计数排序,最后按着桶的顺序进行拼接

6、基数排序

前提:必须知道待排序序列中所有元素的范围,min~max

时间复杂度为O(n)

思路:分为十个桶,从个位,十位,百位···一步步排序,排序的次数根据最大值的位数。

六、树

1、树的定义

零个节点为空树

第一个节点为根节点

最后一个节点为叶节点

子树不相交

:儿子结点个数

树的度:最大结点个数

树的高度:根结点到叶结点的最大值,树的层数

树的深度:根结点到叶结点的最大值,树的层数

结点n的高度:n结点到叶子结点所有路径上包含结点个数的最大值。

2、二叉树

(1)、二叉树

树的度不超过2,空树也是二叉树

(2)、满二叉树

每一层的结点数都达到最大值,比如树有n层,则第n层的叶子结点数为2的n-1次方

(3)、完全二叉树

满二叉树也是完全二叉树,叶结点只能出现在最下层和次下层,并且最下面一层的结点都集中在该层最左边的若干位置。也就是说,完全二叉树出现的位置要和满二叉树一致,不能有右叶子结点而没有左叶子结点
(4)、二叉树的运算
a、深度为n的树,根的高度为1时(默认为0),最多有 (2*n)-1 个结点
b、第n层的树(假设从1层开始数),最多有2*(n-1)个结点
c、空指针域的个数=2n-(n-1)=n+1
(5)、二叉树的五种形态

  1. 空树
  2. 只有根结点的树
  3. 根结点+左结点的二叉树
  4. 根结点+右结点的二叉树
  5. 根结点+左右结点的二叉树

3、树的遍历

思路:根据根结点的位置不同分为前序、中序、后序遍历

(1)、前序遍历

从根结点开始,遍历左子树左结点结束后遍历右结点,以此类推

(2)、中序遍历

从最左叶结点开始遍历,然后到父结点,再到右结点,左子树结束后,遍历根结点,然后到右子树的左结点,以此类推。

(3)、后序遍历

从最左叶结点开始遍历,如果右结点不是叶子结点,则先遍历完叶子结点后遍历父结点,遍历完左右子树后遍历根结点

4、树的表示法

(1)、父结点数组表示法

(2)、儿子链表表示法

(3)、左儿子右兄弟表示法

5、线索二叉树

思路:增加左右线索标志,如果左右子树有值时,则线索标志表示0,如果左右子树没有值时,则线索标志表示1,左线索为一个指针指向前驱结点,右线索为一个指针指向后继结点。

6、二叉搜索树(排序树)

(1)、特点:

a、子树的左结点比右结点小

b、中序排序是有序的

c、在构造二叉树时,每次插入的新结点都是新的叶子结点

d、拥有类似折半查找的特性,又采用了链表作为存储结构,因此是动态查找表的一种适宜表示

(2)、二叉排序树的删除

假设删除的结点为P结点

a、若p结点没有左子树(含叶子结点的情况),则用p结点的右孩子替代它。

b、若p结点没有右子树(含叶子结点的情况),则用p结点的左孩子替代它。

c、若p结点既有左子树又有右子树,则用左子树中最大的结点替代它。

七、散列表(哈希表)

1、数组实现

思路:关键码值映射到表中一个位置来访问记录,设置一个数组,将数字对数组的长度进行模取余进行存放,如果该下标已有数值,则下标进行增加,直到存满为止。

特点:寻址容易,插入和删除困难

2、链表实现

思想:同样设置一个数组,将数字对数组的长度进行模取余进行存放,只是存储的方式是链表。如果下标有数值,则在该数值链上上一个数值。

特点:寻址困难,插入和删除容易。

3、散列技术

(1)、除余法(最常用
(2)、数乘法
(3)、平方取中法
(4)、基数转换法
(5)、随机数法

八、优先队列

1、什么是优先队列

不遵循先进先出的原则,根据优先级进行出列

使用线性数据结构时间复杂度会高,一般使用堆或者树来实现

2、优先队列树和堆

堆的定义:当一颗二叉树的每个结点都大于等于它的两个子结点时,它被成为堆有序。

大根堆:根结点最大,从上向下值不断减少

小根堆:根结点最小,从上向下值不断增加

调整二叉树为大小根堆:

a、(从上向下调整)让当前结点与它的左右孩子进行比较,哪个比较小就和它交换,更新询问节点的下标为被交换的孩子节点下标,否则退出。

b、(从下向上调整)让当前结点和它的父亲节点比较,若比父亲节点小就交换,然后将当前询问的节点下标更新为原父亲节点下标,否则退出。

3、哈夫曼树

(1)、最优二叉树:

a、权值越大的叶子离根越近

b、具有相同带权结点的哈夫曼树不唯一

c、包含n个叶子结点的哈夫曼树中共有2n-1个结点

d、包含n棵树的森林要经过n-1次合并才能形成哈夫曼树,共产生n-1个新结点。

e、满二叉树不一定是哈夫曼树

(2)、如何构造一个哈夫曼树?

a、在 n 个权值中选出两个最小的权值,对应的两个结点组成一个新的二叉树,且新二叉树的根结点的权值为左右孩子权值的和;

b、在原有的 n 个权值中删除那两个最小的权值,同时将新的权值加入到 n–2 个权值的行列中,以此类推;

c、重复 a 和 b (使用递归),直到所有的结点构建成了一棵二叉树为止,这棵树就是哈夫曼树。

(3)、结构元素:weight(结点权重);parent,left,right(父结点、左孩子,右孩子在数组中的位置下标)

(4)、哈夫曼编码:

在建立哈夫曼树后,在左孩子结点设置标为0,右孩子结点设置标为1。用哈夫曼树设计总长最短的二进制前缀编码。

九、并查集

1、什么是并查集

并查集是一种树形结构,又叫“不相交集合”,保持了一组不相交的动态集合,每个集合通过一个代表来识别,代表即集合中的某个成员,通常选择根做这个代表。

2、并查集的实现

主要分为查询和合并两个步骤

查询的核心代码如下

//使用递归的方式进行查询,一层一层访问父节点,直至根节点(根节点的标志就是父节点是本身)。要判断两个元素是否属于同一个集合,只需要看它们的根节点是否相同即可。
int find(int x){
    if(fa[x]==x){
        return x;
    }
    else return find(fa[x]);
}

合并的核心代码如下

//先找到两个集合的代表元素,然后将前者的父节点设为后者即可。
inline void merge(int i,int j){
    fa[find(i)]=find(j);
}

十、图

1、图的重要内容

(1)、有向图

<1,2>符号的集合表示1指向2,1为起点,2为终点

(2)、无向图

(1,2)符号的集合表示边为1和2组成的边

(3)、完全图

顶点为n,边数为e的图,

a、当e=n(n-1)/2的无向图为完全无向图

b、当e=n(n-1)的有向图为完全有向图

(4)、顶点的度

关联该顶点的边的数目,有向图中,顶点的度为入度和出度的和

顶点数n、边数e和度数之间的关系有

边数=各顶点度数和的一半

(5)、连通图

特点:两个不同顶点之间都是连通的

2、邻接矩阵实现图

思路:设置二维数组,设置默认值为0,如果对应的值有边,则变为1

特点:适合存储稠密图

元素:WItem Noedge(无边标记)、int n(顶点数)、int e(边数)、WItem **a(邻接矩阵)

3、邻接表实现图

思路:以每个顶点作为一个单链表,把边进行链接,附带可权值

特点:适合存储稀疏图

元素:int v(边的另一个顶点)、typedef struct Inode *glink; glink next(邻接表的指针),如果有权值则进行增加

4、图的遍历

(1)、广度优先搜索

a、访问顶点v

b、访问顶点v的所有未被访问过的邻接点,假设访问次序是vi1,vi2,…,vit 。

c、按 vi1,vi2,…,vit 的次序,访问每个顶点的所 有未被访问过的邻接点,直到图中所有和初始点 v有路径相通的顶点都被访问过为止。

顺序一致,用队列实现

(2)、深度优先搜索

a、访问顶点v

b、选择一个与顶点v相邻且没被访问过的顶点w, 从w出发深度优先遍历。

c、直到图中与v相邻的所有顶点都被访问过为止。

5、单源最短路径

最短路径问题:如果从图中某一顶点(称为源点)到达另 一顶点(称为终点)的路径可能不止一条,如何找到一条 路径使得沿此路径上各边上的权值总和达到最小。

思路:先求出最短的一条路径,然后将顶点添加到新的集合中,原集合删除该顶点,两条路径选最小者,然后继续寻找最短的路径,以此类推

时间复杂度为O(n的3次方)

6、拓扑排序

拓扑排序是有序排序
步骤:

(1)、从AOV网中选择一个没有前驱(即入度为0)的 顶点并且输出它。

(2)、从AOV网中删去该顶点,并且删去从该顶点发出 的全部有向边。

(3)、重复上述两步,直到剩余的网中不再存在没有前 驱的顶点为止。

特点:使用链表的方式存储

7、最小支撑树

通过深度优先遍历产生的生成树为深度优先生成树

通过广度优先遍历产生的生成树为广度优先生成树

(1)、Prim算法

适合于稠密图

(2)、Krustal算法

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

c语言之数据结构学习心得 的相关文章

  • [Docker]使用Docker部署Kafka

    Kafka 是一个分布式流处理平台 它依赖于 ZooKeeper 作为其协调服务 在 Kafka 集群中 ZooKeeper 负责管理和协调 Kafka 的各个节点 因此 要在 Docker 容器中启动 Kafka 通常需要同时启动一个 Z
  • 对数器的简单使用

    对数器 1 前言 2 内容 简介对数器 以排序算法的检测为实例 3 总结 4 更新日志 1 前言 学习左神的数据结构的过程中 推荐使用对数器检验自己的算法是否正确 2 内容 简介对数器 1 对数器的作用 在一个题目未OJ的时候 可以通过对数
  • Transformer学习笔记

    一 Transformer诞生背景 Transformer模型是解决序列转录问题的一大创新 在Transformer模型之前 序列转录模型都或多或少的基于复杂的循环或卷积神经网络 循环神经网络的计算是时序性的 位置的计算必须基于之前所有位置
  • 微信小程序数据 \n 换行符失效解决办法

    最近遇到一个问题 使用uni app写小程序时 拿到一个字符串 后台返回的 需要在 n 处换行 但是直接使用 let title 黄鹤楼送 n孟浩然之广陵
  • 使用python对银行信息管理系统的简单实现

    一 首先是用户属性的类 class account object 储存用户信息的类 def init self id1 name tel money self id id1 账户 self name name 姓名 self tel tel

随机推荐

  • mo管理器java_Android开发之通过包管理器获取安装应用信息

    最近在自己写一个APP 有一个模块需要获取手机应用的一些信息 坑还是有 但都基本踩过了 自己把他实现了出来 实现方法还是很需要掌握的 底部弹出的对话框中四个选项的实现不多做说明 主要讲讲如何获取这些安装的应用信息 好了 不多说 看看效果图
  • 1024,干程序才懂得节日!

    1024程序员节 1024程序员节是广大程序员的共同节日 1024是2的十次方 二进制计数的基本计量单位之一 针对程序员经常周末加班与工作日熬夜的情况 部分互联网机构倡议每年的10月24日为1024程序员节 在这一天建议程序员拒绝加班 程序
  • 【C/C++】报错问题积累

    1 出现Deprecated declaration XXX give arg types c文件中 有没有参数的函数时 声明需要加void即 main c void fun main h void fun void
  • androidX 在AndroidMainfest里面加入provider后编译不通过

  • 【three.js练习程序】创建简单物理地形

  • ubuntu 18.04 双系统安装

    下载镜像 Ubuntu 18 04 6 LTS Bionic Beaver 磁盘分区用于ubuntu存储 在C盘中分出200M用于ubuntu的引导启动 C盘已经分出200M空间 D盘分配出160G用于存储文件 U盘制作系统盘 刻录软件 推
  • linux下TUN或TAP虚拟网卡的使用

    tun tap 驱动程序实现了虚拟网卡的功能 tun表示虚拟的是点对点设备 tap表示虚拟的是以太网设备 这两种设备针对网络包实施不同的封装 利用tun tap 驱动 可以将tcp ip协议栈处理好的网络分包传给任何一个使用tun tap驱
  • ClickHouse安装(集群版)

    ClickHouse安装 集群版 一 准备工作 1 设置hostname 2 hosts映射 3 关闭防火墙 4 同步时间 5 关闭selinux 6 安装好zookeeper 7 重启 二 搭建ClickHouse集群 1 下载安装包 2
  • c++类模板与继承详解

    c 类模板 继承 详解 类模板和类模板之间 类模板和类之间可以互相继承 它们之间的派生关系有以下四种情况 1 类模板继承类模板 2 类模板继承模板类 3 类模板继承普通类 4 普通类继承模板类 include
  • 【linux】shell 编程之字符串与数组

    前言 对字符串的操作在众多的编程语言中可以说是最基础的了 字符串 String 就是一系列字符的组合 字符串是 Shell 编程中最常用的数据类型之一 除了数字和字符串 也没有其他类型了 一 shell 中字符串的几种格式 在shell中
  • 吃透Chisel语言.18.Chisel模块详解(五)——Chisel中使用Verilog模块

    Chisel模块详解 五 Chisel中使用Verilog模块 上一篇文章讲述了用函数实现轻量级模块的方法 可以大幅度提升编码效率 Chisel中也提供了一些好用的函数 方便我们编写代码 也方便Chisel编译器优化生成的硬件电路 在Chi
  • Blender 之修改器代码分析

    转载 Blender 之修改器代码分析 KAlO2 博客园 Blender 之修改器代码分析 Blender的修改器 modifier 模块 默认界面右下块 Property 面板的扳手 分类 修改 生成 形变 模拟 列出所有的修改器 也可
  • 使用七牛云Python SDK来实现自动下载所有文件

    安装七牛云Python SDK 在终端中输入以下命令 pip install qiniu 连接七牛云存储 创建下载链接并下载文件 示例代码如下 import os from qiniu import Auth BucketManager 配
  • iOS和macOS上Swift编写的EOS区块链开源框架SwiftyEOS

    SwiftyEOS是一个用于与EOS交互的开源框架 用Swift编写 可以在iOS和macOS上使用 特点 EOS密钥对生成 私钥导入 签名哈希 基本的RPC API 链 历史 可查询客户端 交易 EOS token 转账 帮助类处理iOS
  • C/C++语言实现WiFi(socket)数据收发(客户端和服务端)

    目录 客户端 client 服务端 server C C 实现TCP通信 接收WIFI数据 编程环境 VC 6 0 手机端 使用WiFi调试助手 提示 整个过程在局域网中进行 很多编程语言都可以实现socket通信 本博客将通过C C 实现
  • Unity小游戏-勇闯小岛(PC) 项目展示+完整项目源码

    游戏录像 游戏玩法 主角可以变换四种状态 玩家通过四种状态特有的技能来击败眼前的怪物闯关 切换到棕色 有一个一直围绕自己旋转的大摆斧攻击敌人 切换到绿色 可以抵挡一切的投掷物 但是无法攻击敌人 切换到粉色 切换瞬间可以发出飞镖 切换到蓝色
  • gradle 笔记

    1 各种options Simon ZOUYUN PC f AndroidstudioProjects KeyguardTest master gradle help USAGE gradle option task h help Show
  • Linux 进程系统

    Linux 进程系统 守护进程的产生 process namespace namespace 是 Linux 内核用来隔离内核资源的方式 通过 namespace 可以让一些进程只能看到与自己相关的一部分资源 而另外一些进程也只能看到与它们
  • JAVA发展历程

    Java是一门面向对象的编程语言 不仅吸收了C 语言的各种优点 还摒弃了C 里难以理解的多继承 指针等概念 因此Java语言具有功能强大和简单易用两个特征 Java语言作为静态面向对象编程语言的代表 极好地实现了面向对象理论 允许程序员以优
  • c语言之数据结构学习心得

    写在前面 你们好 我是小庄 很高兴能和你们一起学习c语言 如果您对编程感兴趣的话可关注我的动态 写博文是一种习惯 在这过程中能够梳理知识和巩固知识点 一 绪论 1 什么是数据 数据元素 数据项 数据对象 数据结构 1 数据 客观事物的符号表