数据结构与算法基础

本文详细介绍了数组、线性表、链表、稀疏矩阵、队列、栈、二叉树等数据结构,以及它们的存储方式、操作如排序和查找,还涵盖了时间复杂度和空间复杂度的概念,以及图的结构、遍历方法和排序算法如直接插入、希尔排序和快速排序。
摘要由CSDN通过智能技术生成

数组

数组类型存储地址计算
一维数组a[n]a[i]的存储地址为:a+i*len (len为各元素占得字节数)
二维数组a[m][n]a[i][j]的存储地址(按行存储)为:a+(i*n+j)*len
a[i][j]的存储地址(按列存储)为:a+(*m+i)*Ien

稀疏矩阵

在这里插入图片描述

线性表

  • 顺序表
  • 链表
    • 单链表
    • 循环链表
    • 双向链表

顺序存储与链式存储

在这里插入图片描述

队列与栈

  • 队列:先进先出

  • 栈:先进后出

循环队列:头指针和尾指针指向同一个位置

队空:head=tail

队满:(tail+1)%size=head

广义表

广义表是n个表元素组成的有限序列,是线性表的推广。
通常用递归的形式进行定义,记做: L S = ( a o , a 1 , ⋯   , a n ) LS=(a_o,a_1,\cdots,a_n) LS=(ao,a1,,an)

树与二叉树

  • 结点的度:结点有多少个分子就是有多少度
  • 树的度:树中结点的度最大的为树的度
  • 叶子结点:没有子结点的
  • 分支结点:有子结点的
  • 内部结点:非叶子结点和根结点,中间的结点
  • 父结点
  • 子结点
  • 兄弟结点
  • 层次

二叉树的重要特性:

  1. 在二叉树的第i层上最多有 2 i − 1 2^{i-1} 2i1个结点(i≥1)
  2. 深度为k的二叉树品多有 2 k − 1 2^{k-1} 2k1个结点(k≥1)
  3. 对任何一棵二叉树,如果其叶子结点数为 n 0 n_0 n0,度为2的结点数为 n 2 n_2 n2,则 n 0 = n 2 + 1 n_0=n_2+1 n0=n2+1
  4. 如果对一棵有个结点的完全二叉树的结点按层序编号(从第1层到 ⌊ l o g 2 n + 1 ⌋ \lfloor log2n+1 \rfloor log2n+1层,每层从左到右),则对任一结
    i ( 1 ≤ i ≤ n ) i(1\leq i \leq n) i(1in),有:
    • 如果i=1,则结点无父结点,是二叉树的根:如果i>1,则父结点是 ⌊ i / 2 ⌋ \lfloor i/2 \rfloor i/2
    • 如果2i>n,则结点为叶子结点,无左子结点:否则,其左子结点是结点2i:
    • 如果2i+1>n,则结点无右子叶点,否则,其右子结点是结点2i+1。

满二叉树

所有结点都是满的

完全二叉树

除叶子结点外的其他结点都是满的,叶子结点必须由左往右填充的

二叉树的遍历

  • 前序遍历:先访问根节点,再访问左结点,再访右问结点
  • 中序遍历:先访问左结点,再访问根节点,再访问右结点
  • 后序遍历:先访问左结点,再访问右结点,再访问根节点
  • 层次遍历

反向构造二叉树

需要知道二叉树的前序遍历和中序遍历,步骤:

  1. 在前序遍历中找都第一个元素,作为根结点;
  2. 在中序遍历找到根结点,将中序遍历分为两半,在根结点左边的是根结点的左结点树,在根结点右边的是根结点的右结点树。
  3. 重复第1,2步将构造第2步划分的左结点树和右结点树

树转二叉树

  • 孩子结点-左子树结点
  • 兄弟结点-右孩子结点

查找二叉树

  • 二叉排序树
  • 左孩子小于根
  • 右孩子大于根

插入结点

  • 若该键值结点已存在,则不再插入,如:48
  • 若查找二叉树为空树,则以新结点为查找二叉树
  • 将要插入结点键值与插入后父结点键值比较,就能确定新结点是父结点的左子结点,还是右子结点。

删除结点

  • 若待删除结点是叶子结点,则直接删除
  • 若待删除结点只有一个子结点,则将这个子结点与待删除结点的父结点直接连接,如:56
  • 若待删除的结点有两个子结点,则在其左子树上,用中序遍历寻找关键值最大的结点s,用结点s的值代替结点P的值,然后删除节点s,节点s必属于上述①,②情况之一,如89。

最优二叉树(哈夫曼树)

需要了解的基本概念:

  • 树的路径长度
  • 带权路径长度
  • 树的带权路径长度(树的代价)

构造最优二叉树步骤:

  1. 在权值中取出两个最小的,并将这两个权值相加得到新的权值
  2. 新的权值作为父结点,最小的两个权值中,大的作为左子结点,小的作为右子结点。
  3. 将新的权值放回全部权值中,删除刚刚取出两个最小的权值。重复第1,2步骤构造最优二叉树步骤

平衡二叉树

  • 任意结点的左右子树深度相差不超过1
  • 每结点的平衡度只能为-1、0或1

有向图:边是有箭头的

无向图:边是没有箭头的

完全图

  • 在无向图中,若每对顶点之间都有一条边相连,则称该图为完全图(complete graph)。
  • 在有向图中,若每对顶点之间都有二条有向边相互连接,则称该图为完全图。

图的存储-邻接矩阵

用一个阶方阵R来存放图中各结点的关联信息,其矩阵元素 R i j R_{ij} Rij定义为
在这里插入图片描述

图的存储-邻接表

首先把每个顶点的邻接顶点用链表示出来,然后用一个一维数组来顺序存储上面每个链表的头指针。

在这里插入图片描述

图的遍历

在这里插入图片描述

拓扑排序

我们把用有向边表示活动之间开始的先后关系。这种有向图称为用顶点表示活动网络,简称AOV网络。

算法

时间复杂度是指程序运行从开始到结束所需要的时间。通常分析时间复杂度的方法是从算法中选取一种对于所研究的问题来说是基本运算的操作以该操作重复执行的次数作为算法的时间度量。一般来说,算法中原操作重复执行的次数是规模的某个函数T(n)。由于许多情况下要精确计算T(n)是困难的,因此引入了渐进时间复杂度在数量上估计一个算法的执行时间。其定义如下:

如果存在两个常数c和m,对于所有的n,当n≥m时有 f ( n ) ≤ c g ( n ) f(n)≤cg(n) f(n)cg(n)则有 f ( n ) = O ( g ( n ) ) f(n)=O(g(n)) f(n)=O(g(n))。也就是说,随着n的增大,f(n)渐进地不大于g(n)。例如,一个程序的实际执行时间为 T ( n ) = 3 n 3 + 2 n 2 + n T(n)=3n^3+2n^2+n T(n)=3n3+2n2+n,则 T ( n ) = o ( n 3 ) T(n)=o(n^3) T(n)=o(n3)
常见的对算法执行所需时间的度量
O ( 1 ) < O ( log ⁡ 2 n ) < O ( n ) < O ( n log ⁡ 2 n ) < O ( n 2 ) < O ( n 3 ) < O ( 2 n ) O(1)<O(\log_2n)<O(n)<O(n\log_2n)<O(n^2)<O(n^3)<O(2^n) O(1)<O(log2n)<O(n)<O(nlog2n)<O(n2)<O(n3)<O(2n)

空间复杂度是指对一个算法在运行过程中临时占用存储空间大小的度量一个算法的空间复杂度只考虑在运行过程中为局部变量分配的存储空间的大小

顺序查找

顺序查找的思想:将待查找的关键字为key的元素从头到尾与表中元素进行比较,如果中间存在关键字为key的元素,则返回成功:否则,则查找失败。

时间复杂度为 O ( n ) O(n) O(n)

二分查找

时间复杂度为 O ( log ⁡ 2 n ) O(\log_2n) O(log2n)

散列表

散列表查找的基本思想是:已知关键字集合U,最大关键字为,设计一个函数Hash,它以关键字为自变量,关键字的存储地址为因变量,将关键字映射到一个有限的、地址连续的区间 T [ 0 ⋯ n − 1 ] ( n < < m ) T[0\cdots n-1](n<<m) T[0n1](n<<m)中,这个区间就称为散列表,散列查找中使用的转换函数称为散列函数。

排序

在这里插入图片描述

直接插入法

即当插入第i个记录时, R 1 , R 2 , ⋯   , R n − 1 R_1,R_2,\cdots,R_{n-1} R1,R2,,Rn1均已好序,因此,将第个记录R依次与 R n − 1 , ⋯   , R 2 , R 1 R_{n-1},\cdots,R_2,R_1 Rn1,,R2,R1进行比较,找到合适的位置插入。它简单明了,但速度很慢。

希尔排序

先取一个小于n的整数 d 1 d_1 d1作为第一个增量,把文件的全部记录分成 d 1 d_1 d1个组。所有距离为 d 1 d_1 d1的倍数的记录放在同一个组中。先在各组内进行直接插入排序然后,取第二个增量 d 2 < d 1 d_2<d_1 d2<d1重复上述的分组和排序,直至所取的增量 d t = 1 ( d t < d t − 1 < O < d 2 < d 1 ) d_t=1(d_t<d_{t-1}<O<d_2<d_1) dt=1(dt<dt1<O<d2<d1),即所有记录放在同一组中进行直接插入排序为止。该方法实质上是种分组插入方法。

直接选择排序

直接选择排序的过程是,首先在所有记录中选出排序码最小的记录,把它与第1个记录交换,然后在其余的记录内选出排序码最小的记录,与第2个记录交换…依次类推,直到所有记录排完为止。

冒泡排序

通过相邻元素之间的比较和交换,将排序码较小的元素逐渐从底部移向顶部。由于整个排序的过程就像水底下的气泡一样逐渐向上冒,因此称为冒泡算法。

快速排序

快速排序采用的是分治法,其基本思想是将原问题分解成若干个规摸更小但结构与原问题相似的子问题。通过递归地解决这些子问题,然后再将这些子问题的解组合成原问题的解。
快速排序通常包括两个步骤:

  1. 在待排序的个记录中任取一个记录,以该记录的排序码为准,将所有记录都分成两组,第1组都小于该数,第2组都大于该数,如图所示。
  2. 采用相同的方法对左、右两组分别进行排序,直到所有记录都排到相应的位置为止

在这里插入图片描述

归并排序

归并也称为合并,是将两个或两个以上的有序子表合并成一个新的有序表。若将两个有序表合并成一个有序表,则称为二路合并。合并的过程是:比较A[i]和A[j]的排序码大小,若A[i]的排序码小于等于A[j]的排序码,则将第一个有序表中的元素A[i]复制到R[k]中,并令和k分别加1;如此循环下去,直到其中一个有序表比较和复制完,然后再将另一个有序表的剩余元素复制到R中。

  • 17
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值