大家好,关于深入解析:基础数据结构与算法原理很多朋友都还不太明白,不过没关系,因为今天小编就来为大家分享关于的知识点,相信应该可以解决大家的一些困惑和问题,如果碰巧可以解决您的问题,还望关注下本站哦,希望对各位有所帮助!
这篇文章主要讲的是基本的数据结构和算法概念。有些地方可能会涉及到更高级的算法和算法。具体内容稍后单独写。另外,一些属性会不断添加,希望得到您的建议,谢谢。
数据结构
程序=数据结构+算法
数据结构基本概念
数据的逻辑结构:反映数据元素之间关系的数据元素集合的表示。数据的逻辑结构包括四种类型:集合、线性结构、树形结构和图形结构。数据存储结构:数据逻辑结构在计算机存储空间中的存储形式称为数据存储结构。常用的存储结构有顺序、链接、索引等存储结构。在数据结构中,没有前件的节点称为根节点,没有后件的节点称为终端节点。
数据结构的基本操作插入和删除是数据结构的两个基本操作。此外,还有搜索、分类、合并、分解、复制和修改等。
线性结构和非线性结构根据数据结构中各数据元素之间关系的复杂程度,数据结构一般分为线性结构和非线性结构两种。
线性结构:有且只有一个根节点;每个节点至多有一个前因和至多一个后因。非线性结构:如果数据结构不是线性结构,则称为非线性结构。本文涵盖以下内容:
四种线性结构的存储结构:序列表、链表、索引、哈希。两种常见的线性逻辑结构:队列、栈。非线性逻辑结构:循环队列、双向队列、双向循环队列、树,图
存储结构
:010 -1010 顺序表是线性表的顺序存储结构,是指使用一组地址连续的存储单元来按顺序存储线性表的数据元素。
序列表有以下两个基本特征:
序列表中所有元素所占用的存储空间是连续的;序列表中的每个数据元素按照逻辑顺序存储在存储空间中。假设序列表的每个元素需要占用K个存储单元,则将占用的第一个单元的存储地址作为数据元素的存储位置。那么序列表中第i+1个数据元素的存储位置LOC(a_i+1)与第i个数据元素的存储位置LOC(a_i)满足如下关系:
LOC(a_(i+1))=LOC(a_i)+K
LOC(a_i)=LOC(a_1)+(i-1)*K
其中,LOC(a_1)是序列表的第一个数据元素a_1的存储位置,通常称为序列表的起始位置或基地址。顺序存储结构也称为随机存取结构。
顺序表常见操作(括号内为算法的平均时间复杂度,未指定的具体复杂度取决于不同的算法和运算规则):
插入(O(n))、删除(O(n))、查找、排序、分解、合并、复制(O(n))、反转(O(n))
顺序表
链表是指线性表的链接存储结构。一组任意存储单元存储线性表的数据元素。因此,为了表达每个数据元素a_i与其直接后继数据元素a_(i+1)之间的逻辑关系,对于数据元素a_i,除了存储自身信息(数据字段)之外,还存储一个变量需要存储以指示其直接后继信息(指针字段)。这两部分信息构成了数据元素a_i的存储映像,称为节点。 N个节点链接成一个链表。该链表是一种传统的单向链表。
有时,我们会在单链表的第一个节点之前附加一个节点,称为头节点,它指向链表中的第一个节点。头节点的数据字段可以不存储任何信息,也可以存储线性表的长度等附加信息。头节点的指针字段存储指向第一个节点的指针。在单向链表中,要获取第i个数据元素,必须从头指针开始查找。因此,链表是一种非随机访问的存储结构。
上述链表指针字段只包含一个指针,指向下一个数据的地址。如果我们将链表最后一个节点指针域的指针指向链表头节点的地址,就形成了一个环形的存储结构。我们称之为循环链表。
当然,我们可以在每个节点的指针字段中再添加一个指针,指向前一个数据节点的地址,从而形成一个双向链表,将头节点的前一个节点指向尾节点,并在同时将尾节点的下一个节点指向头节点,形成双向循环链表。
如果链表的尾节点的指针字段指向链表中的任何前一个节点,我们称该链表为循环链表。环链表是特殊情况之一
顺序表常见操作(括号内为算法的平均时间复杂度,未指定的具体复杂度取决于不同的算法和运算规则):
插入(O(n))、删除(O(n))、查找、排序、分解、合并、复制(O(n))、反转(O(n))
链表
除了创建存储节点信息外,索引存储还创建额外的索引表来标识节点地址。索引表由若干个索引项组成。
理解索引的最好例子是《新华字典》,它创建了两组索引表(拼音、部首)。字典的正文是从“啊”到“做”的每个单词的解释。有几千页,这就是数据。前面的拼音/部首是索引表。索引表告诉您某个发音/部首位于哪一页。这就像一个指向数据地址的指针。索引表可以是一级索引表,也可以是多级索引表。例如,字典中的部首索引是两级的。
索引存储结构利用节点的索引号来确定节点存储地址。优点是检索速度快,缺点是增加了额外的索引表,占用存储空间较多。
索引
散列存储又称散列存储,是一种试图在数据元素的存储位置(保留的连续存储区域)与关键码之间建立明确对应关系的搜索技术。哈希存储的基本思想是节点的键码值决定了节点的存储地址。哈希技术除了用于存储之外,还可以用于查找。
Hash将数据中每个元素的关键字K作为自变量,通过哈希函数H(k)计算函数值,将函数值作为连续存储空间的单元地址,将元素存储到函数中相应单位的值。由于函数值唯一,因此搜索时间复杂度为O(1)
散列
线性逻辑结构
线性工作台满足以下特性:
有且仅有一个根节点a_1,无先行词;终端节点a_n只有一个,无后件;除根节点和终端节点外,其他所有节点都有且只有一个前件,并且它们也有且只有一个后件。线性表中的节点数n称为线性表的长度。当n=0时,称为空列表。
线性表
栈实际上是一个线性表,只不过是一个特殊的线性表。栈是一种线性表,只能在表的一端进行插入和删除操作。这一端通常称为栈顶(TOP),另一端称为栈底(BOTTOM)。当列表中没有元素时,堆栈称为空堆栈。栈顶元素始终是最后一个要插入(压入)的元素,因此也是第一个要删除(弹出)的元素;堆栈的底部元素始终是第一个要插入的元素,因此也是最后一个要删除的元素。所以栈是后进先出(LIFO)的数据结构
栈的基本运算有三种:压入、出栈、读取栈顶的时间复杂度为O(1)
栈
队列是一种序列表,只允许一端删除,另一端插入。允许删除的一端称为队列的头部。对端指针front指向对端头元素的下一个元素。允许插入的一端称为队列尾部。使用队列的尾部。指针rear指向队列中的尾部元素。因此,从front指针指向的下一个位置到rear指针rear指向的位置的所有元素都是队列中的元素。
对队列的修改为先进先出(FIFO)。将一个元素插入到队列末尾称为入队操作。从对端删除一个元素称为出队操作。
队列主要有两个基本操作:入队操作和出队操作,其复杂度为O(1)
队列
在实际应用中,队列的顺序存储结构一般采用循环队列的形式。所谓循环队列,就是将队列存储空间的最后一个位置移动到第一个位置,形成逻辑上的环形空间。实际使用循环队列时,为了区分满队列和空队列,通常需要添加标志S。
循环队列主要有两个基本操作:入队操作和出队操作,复杂度为O(1)
入队操作
意思是在循环队列的末尾添加一个新元素。首先,后=后+1。当rear=m+1时,设置rear=1,然后将新元素插入到rear指针指向的位置。当S=1,rear=front时,表示队列已满,无法进行队列操作,称为“溢出”。退出操作
指从循环队列的头部退出一个元素,并将其赋值给指定的变量。首先,front=front+1,当front=m+1时,设置front=1,然后将头指针指向的元素赋值给指定的变量。当循环队列为空S=0时,无法进行出队操作,这种情况就变成“下溢”。
循环队列
非线性逻辑结构
树是一种简单的非线性结构。树形结构具有以下特点:
每个节点只有一个前件,称为父节点,并且只有一个没有前件的节点,称为树的根节点。每个节点可以有多个后续节点,称为该节点的子节点。没有后继的节点称为叶节点。一个节点的后继者数量称为该节点的度。树的最高层数称为树的深度。
树
二叉树是一种树结构,通常采用链式存储结构,满足以下特点:
其特点是每个节点最多有两个子树(即二叉树中不存在度大于2的节点);二叉树的子树可以分为左子树和右子树,并且它们的顺序不能任意颠倒。二叉树的基本性质二叉树的第i 层最多有2i-1 个节点。深度为k 的二叉树最多有2k-1 个节点(k=1)。在任意二叉树中,度为0的节点总有一个比度为2的节点多N个节点的二叉树,其深度至少为floor(log N) + 1。 哈夫曼树的加权路径长度是len=2n+1; n 是所有叶子权重的总和。二叉树的遍历就是按照一定的顺序,访问二叉树中的所有节点,使得每个节点只被访问一次。分为以下几类:
前序遍历(DLR):首先访问根节点,然后遍历左子树,最后遍历右子树。中序遍历(LDR):首先遍历左子树,然后是根节点,最后是右子树。后序遍历(LRD): 先遍历左子树,再遍历右子树,最后访问根节点。此外,图遍历还可以用在树上,包括:
广度优先遍历(层序遍历):从根节点开始,从左到右向下逐层遍历。深度优先遍历:从根节点开始,沿着左子树遍历到叶子节点,然后逐层向上遍历右子树。此外,还有很多特殊的二叉树,其特点是:
满二叉树:除最后一层外,每一层的所有节点都有两个子节点。满二叉树的第K层有2^(K-1)个节点,深度为M的满二叉树有2M-1个节点。完全二叉树:除最后一层外,每一层的节点数均达到最大值;最后一层仅缺少右侧的几个节点。 N 个节点的完全二叉树的深度为Floor(log_2 N) + 1。完全二叉树的总点数为N,因此叶子节点的数量为ceil(N/2)
二叉树
。最常见的完全二叉树是堆。该堆满足以下条件
堆中节点的值始终不大于或不小于其父节点的值。堆始终是完全二叉树。根节点最大的堆称为最大堆或大根堆,根节点最小的堆称为最小堆或小根堆。称为常用的哈希函数或链地址法(拉链法)。
堆有以下基本操作:
插入: 在堆中插入新元素获取: 获取当前堆顶元素的值删除: 删除包含堆顶元素: 判断堆中是否存在元素
堆
线性探针法直接寻址方式: H(k) 是线性函数,如果该位置已经有值,则向下查找第一个空的位置作为哈希地址。求中间方法:取k个平方之后的值的中间数字作为哈希地址。数字分析法: 对于比较规则k 值,找出差异较大的部分,作为哈希地址折叠法: 将k 分成许多部分,然后进行模二和作为哈希地址余数法: H(k)=k % p, p=m ,其中p是素数,m是表的长度。随机数方法:将密钥的随机值作为哈希地址。当使用密钥长度时,用于实现映射的函数是哈希函数。简单的哈希可能会引起冲突(不同的输入得到相同的输出),为了防止冲突,可以考虑以下方法:
平均查找长度: 发生碰撞时,碰撞的数据元素连接到同一个单链表,新元素插入到链表前端哈希表相关特性: 线性探测法地址增量d D_1={1, 2,3, m-1},i为检测次数,m为表长度,当该方法遇到冲突地址时,会依次检测下一个地址(d=d_i + 1) 直到有空地址。如果没有找到空地址,则溢出。图的分类线性探针法计算平均长度(其中m为表中数据长度,n为表长度):ASL_s=d_1 + d_2 + . + d_m)/m,查找成功
ASL_u=(d_1 + d_2 + . + d_n)/n,搜索失败
注:线性探测法成功时,d_i 为每次放入元素时的地址增量。不成功时,d_i 为查找每个元素到表长度中下一个空地址的地址增量(索引为在表长度中)。内循环)
采用链地址法计算平均长度(其中k为最长链长,m为表中数据长度,n为表长度): ASL_s=((1~k)(当前层指针个数*当前层个))/米,搜索成功
ASL_u=((1~n)(当前位置链长度))/n,搜索失败
图的遍历线性探针法容易“聚集”,影响查找效率,而链地址法无法适应表长度不确定的情况。填充因子()=哈希表中的记录数/哈希表的长度
哈希表
图的定义有两种:
元组的定义:图G是一个有序元组(V,E),其中V称为顶点集,E称为边集,E和V不相交。它们也可以写成V(G)和E(G)。 E的元素都是元组,用(x,y)表示,其中x,y为; V三元组的定义: 图G指的是一个三元组(V,E,I),其中V称为顶集,E称为边集,E和V不相交; I 称为相关函数,I 将E 中的每个元素映射到V * V。如果将e 映射到(u,v),则称边e 连接顶点u,v,而u,v 称为e 的端点,其中u、v 与e 相邻。同时,如果两条边i、j有公共顶点u,则称i、j与u相邻。算法复杂度张图片有不同的分类规则,如下:
第1 类
有向图: 如果图中顶点之间的关系不仅是连通或不连通的,而且还能区分两侧顶点的入和出(有出边和入边),那么它就是有向图。无向图: 如果图中顶点之间的关系只是连通或不连通,而不区分两侧顶点的入和出(没有出入边),则为无向图。
单图分类2
循环图: 单向遍历可以返回到遍历过的点,如循环链表: 非循环图: 单向遍历不能返回到遍历过的点,如树分类3
加权图: 图的边具有带有有关边的信息的权重。例如,地图中两点之间的距离未加权图表: 图表的每条边都没有包含有关边的信息的权重。仅表示是否与他人连接
单图: 如果任意两个顶点之间只有一条边且边集不包含环,则该图称为单图。图的表示形式采用邻接矩阵和树状形式(顶点指针字段是指针数组),其具有以下特点:
无向图的邻接矩阵是对称矩阵。加权图矩阵中的元素是全职的。在未加权图中,0/1 用于指示断开/连接的主对角线中存在非零元素。图必须有环010- 59000 广度优先遍历: 广度优先遍历是连通图的一种遍历策略。因为它的思想是从一个顶点V_0开始,先径向遍历它周围更广阔的区域。图深度优先遍历的相关性质:
具有N 个顶点的连通图中的边数至少为N-1。有N个顶点的强连通图的边数至少是N。广度优先遍历用于在无权图中寻找最短路径(带权图其实也可以,东西比较多)呗)
图
操作,添加、删除、查找、使用条件数组O(n)O(n)O(n)、数字固定下标链表O(1)O(n)O(n)、修改变长数组O(1)结束)O(n)O(n) 不定下标堆栈O(1)O(1) LIFO 队列O(1)O(1) FIFO 哈希表O(1)O(1)O(1) 键操作,无序树字典O(log n)O(log n)O(log n)键操作,有序哈希集O(1)O(1)O(1) 唯一值,无序树集O(log n)O(log n )O(log n) 唯一值,有序
简单数据结构的增删改查
算法
算法的基本特征:可行性、确定性、有限性算法的基本要素:算法中数据的计算和运算、算法的控制结构算法。算法设计的基本方法:穷举法、动态规划、贪心法、回溯法、递归法、递推法、分而治之法、哈希法、分支定界法。算法设计的要求:正确性、可读性、鲁棒性、高效性和低存储要求算法的基本结构:序列、循环、选择排序算法时间复杂度算法的时间复杂度:指执行算法所需的计算工作量(并不代表算法实际需要的时间) 算法的空间复杂度:执行这个算法需要额外的内存空间(代表算法实际需要的空间) 复杂度表示方法: 用大写O表示:O(n)指时间复杂度完成n次数据处理需要n个单位的时间;在表达空间复杂度时,是指完成n次数据处理需要使用n个单位的辅助空间。
算法基本概念
字符串算法除了加、删、改、查之外,还有很多匹配算法,比如大家最熟悉的KMP算法(不是基础部分的一部分)。以下是相关算法的一些属性:
长度为n 的字符串有n(n+1)/2+1 个子串n 个字符串,其中的字符不同,则S 中互不相同的非平凡子串为frac{1}{ 2}n^2+ frac{1}{2}n-1
字符串算法
排序算法实际上可以分为内排序和外排序:
内部排序:排序过程中,所有元素都被排序到内存中,称为内部排序。内排序是排序的基础。内部排序的效率是通过比较的次数来衡量的。根据采用的策略不同,内部排序可分为插入排序、选择排序、堆排序、归并排序、冒泡排序、快速排序、希尔排序、基数排序等。 外部排序:当数据量较大时,只能按块排序,但不能保证块之间的顺序。外部排序通过外部存储器的读/写次数来衡量其效率。010-59000排序算法分为以下几类:
插入排序:插入排序、希尔排序交换排序:冒泡排序、快速排序选择排序:选择排序、堆排序归并排序基数排序算法时间复杂度(最佳) 时间复杂度(最佳) 时间复杂度度(最差)空间复杂度稳定插入排序O(n^2)O(n)O(n^2)O(1) 稳定希尔排序O(n^{1.3})O(n)O( n^2)O(1) 不稳定选择排序O( n^2)O(n^2)O(n^2)O(1) 不稳定堆排序O(nlog n)O(nlog n)O( nlog n)O(1) 不稳定冒泡排序O(n^2 )O(n)O(n^2)O(1) 稳定快速排序O(nlog n)O(nlog n)O(n^2 )O(nlog n) 不稳定归并排序O(nlog n)O(nlog n)O(nlog n)O(n) 稳定基数排序O(d(r+n))O(d(n+rd)) O(d(r+n))O(n+rd) 稳定注释:
【深入解析:基础数据结构与算法原理】相关文章:
2.米颠拜石
3.王羲之临池学书
8.郑板桥轶事十则
用户评论
这是想学编程必修课啊!
有20位网友表示赞同!
以前听说过这些名词,但始终没有深入了解过。
有7位网友表示赞同!
感觉这个知识点很有深度,需要慢慢琢磨。
有14位网友表示赞同!
学习这些概念能更好地理解代码逻辑吧。
有9位网友表示赞同!
数据结构和算法真是一块好基础!
有8位网友表示赞同!
打算先补一下基础知识再开始写程序。
有8位网友表示赞同!
希望能学到一些实用的技巧,能够提升我的编程效率。
有18位网友表示赞同!
学习这门课感觉就像在打基础建设房子!稳稳的。
有10位网友表示赞同!
想要入门软件开发,这些概念是必须掌握的啊。
有20位网友表示赞同!
好期待能把学的知识运用到实际项目中去!
有9位网友表示赞同!
不知道学完会有多厉害的感覺?
有19位网友表示赞同!
有没有学习规划和资料分享啊?
有9位网友表示赞同!
这方面基础真的很重要,尤其要做大型项目的开发!
有17位网友表示赞同!
我一直对算法比较感兴趣,感觉很有挑战性。
有14位网友表示赞同!
希望能像大神一般运用数据结构来解决问题!
有15位网友表示赞同!
这些概念看起来还挺抽象的,需要好好想想!
有17位网友表示赞同!
学完以后是不是就能写出更优雅、高效的代码?
有17位网友表示赞同!
最近在项目做遇到了算法方面的瓶颈,希望这门课能帮我解决!
有6位网友表示赞同!
感觉学习数据结构和算法是一个很好的投资!
有19位网友表示赞同!
这个课程看起来很有价值,值得我花时间去学习。
有8位网友表示赞同!