Skip to content

Latest commit

 

History

History
193 lines (114 loc) · 5.41 KB

33-数据结构与算法.md

File metadata and controls

193 lines (114 loc) · 5.41 KB

数据结构与算法

数据本质:

数据结构是现实世界的数据抽象的存储在物理设备上,将现实数据抽象成最小单元的数据,包括:数据本身的值,数据与数据的关系。

物理设备有两种存储方式,连续的存储(数组)、不连续的存储(链表)

由这两种方式,进一步抽象出其他结构:集合、树、图

算法本质:

已最有效率的方式穷举所有可能性,寻找计算结果。

基础

空间复杂度 S(n) space

时间复杂度 T(n) time

考虑两种情况:最坏情况复杂度 Tworst(n)、平均复杂度 Tavg(n)

算法复杂度的直观体现

image-20250121164420148

image-20250121164541972

数组、链表

数据存储例子:

存储函数(一元多项式):f(x) = ax2 + bx + c

1.可以使用数组记录,索引表示几次方,值表示系数

f(x) = [c,b,a]

2.如果 x 项的平方很大,系数有很多零,会造成浪费,可以在数组存储一个对象

f(x) = [(a,2), (b,1),(c,0)]

函数的计算,就是两个数组间的合并操作。

如果用数组时,2 的情况下,需要很多移位的操作,如果用链表就会很快。

十字链表存储二维稀疏矩阵

1.只存储矩阵非0元素项

2.每个节点通过两个指针,行指针、列指针串起来

堆、栈

计算机运算表达式

1.中缀表达式:运算符号位于两个运算数之间。a + b * c - d / e

2.后缀表达式:预算符号位于两个运算数之后。abc * + de / -

例子:6 2 / 3 - 4 2 * + = ?

6 2 / 3 - 4 2 * +
// 6 2 / = 3
3 3 - 4 2 * + 
// 3 - 3 = 0
0 4 2 * +
// 0 先入栈 计算 4 * 2 = 8
0 8 +
// 0 + 8 = 8

这就是一种栈规律的计算(后入先出)。

1.可以用一个一维数组实现和一个记录栈顶元素位置的变量组成。

2.也可以用一个单向链表来实现,栈顶元素是头节点。

中缀转后缀

image-20250122164817775

从头到尾读取中缀的每个对象,处理规则如下:

  1. 运算数:直接输出
  2. 左括号:压入栈中
  3. 右括号:弹出左括号上面的所有运算符号
  4. 运算符:和栈顶的运算符比较优先级,大于入栈,小于或等于弹出,再次比较,直到栈顶大于为止,然后入栈
  5. 对象处理完毕,栈中所有运算符出栈

队列

队列只能从一边进,另一边出。

数组实现:一个一维数组,一个记录头元素,一个记录尾元素的变脸组成。特殊结构:顺环队列(头尾相连)。

链表实现:一个单向链表,头删除,尾插入。

一对多关系的集合,有一个根节点,叶子节点等。

二分查找:时间复杂度 logn

使用 儿子-兄弟表示法

image-20250123151017517

也可以看成是二叉树。

二叉树是左,右子节点,相当于二分查找,要么左,要么右。

特殊的完全二叉树可以使用数组存储,因为是满的,都是连续的,中间没有断的,这种符合数组的存储结构。

一般二叉树可以将其补成完全二叉树,再用数组存储,但是会空很多位置。

链表存储二叉树,左节点、子节点的头、右节点,没有就 null。

常用的遍历方法(重点):

  1. 先序 - 根、左子树、右子树
  2. 中序 - 左子树、根、右子树
  3. 后序 - 左子树、右子树、根
  4. 层次遍历 - 上到下、左到右
// 先序
public void PreOrderTraversal( BinTree BT ){
	if( BT ){
        // 根
        printf("%d", BT.value);
        // 左边
        PreOrderTraversal( BT.left );
        // 右边
        PreOrderTraversal( BT.right );
    }
}

先序:

输出结果:A ( B D F E ) ( B G H I )

image-20250123164005336

中序:

输出结果:( D B E F ) A ( G H C I )

image-20250123164908424

后序:

输出结果:( D E F B ) ( H G I C ) A

image-20250123165035703

堆栈思想遍历算法:

每一个节点判断是否有子节点,有就进栈,直到没有子节点的节点,抛出节点元素,出栈,在看栈顶是否有其他子节点,有继续进栈,没有就重复抛出。

层序遍历:

二叉树遍历的本质是二维结构的线性化,堆栈是暂存了节点,因为不存储就无法找到右节点。

层序使用队列进行线性化,一层一层的遍历,先进入节点,然后打印节点,进入左右节点,然后在继续循环打印、进入,直到无子节点。

遍历的基础上,变形

  1. 输出二叉树中的叶子节点:遍历时,添加左右都为空的判断
  2. 二叉树的高度:利用后续遍历,分别求出左右子树高度,然后 max + 1
  3. 运算表达式:
  4. 两种遍历序列确定二叉树(必须要有中序)

二叉搜索树

满足条件,

  1. 左子树的所有值小于右子树
  2. 右子树的所有值大于左子树
  3. 左右子树都是二叉搜索树

小的在左边,大的在右边

操作:

  1. 查找指定值的地址(尾递归、循环都可以实现)
  2. 最大值(最右边的值)、最小值(最左边的值)
  3. 插入
  4. 删除