数据结构笔记

数据结构学习笔记

1.概念

数据:

  • 可输入性
  • 可识别性和处理性
  • 符号集合

数据元素:

  • 数据的基本单位
  • 整体考虑

数据项:

  • 最小单位

关键字:

  • 主关键字:唯一识别
  • 次关键字

数据对象:

  • 同性质的数据元素集合

数据结构:

  • 内容:

    • 逻辑结构:抽象的数据模型。用户视图,面向问题

      • 集合
      • 线性(1 to 1)
      • 树(1 to n)
      • 图(n to n)
    • 存储结构(物理):逻辑结构在计算机中的表示。面向计算机,实现视图

      • 顺序(相邻元素物理位置相邻)
      • 链式(相邻元素指针实现相邻)
      • 散列(关键字定地址)
      • 索引
  • 性质:

    • 存在相互联系
    • 数据元素集合
  • 形式定义:(D,R)

    • D:数据元素有限集

    • R:D上的关系有限集

      D = { a , b , c , d }

      R = { ( a , b ) , ( a , c ) , ( b , d ) }

      在这里插入图片描述


数据类型:(值 + 操作)DT

  • 值的结合
  • 值集上的操作

抽象数据类型:(数据结构 + 操作)ADT

  • 数据结构

  • 其结构上的操作

  • 可用(D,S,P)表示

    • D:数据对象

    • S:D上关系集

    • P:对D的操作集

      ADT Complex{					//ADT 类型名{
          D = { e1 , e2 },			//	  数据对象
          R = { < e1 , e2 >},			//	  数据关系
          InitComplex( &Z , v1 , v2 )	//	  基本操作
      }ADT Complex					//	  }ADT 类型名
      

算法:指令的有限序列

  • 有穷
  • 确定(无二义性)
  • 可行
  • 输入(可以没有输入)
  • 输出

算法分析:

  • 时间复杂度
  • 空间复杂度

2.算法分析

算法分析-----大"O"符号

  • 若两个正常数 c , n0 ,对任意n >= n0 都有T(n) <= c × f(n), 则称T(n) = O(f(n))


  • A ( n ) = a m n m + a m − 1 n m − 1 + . . . a 0 A(n) = a_mn^m + a_{m-1}n^{m-1} + ...a_0 A(n)=amnm+am1nm1+...a0
    是一个m次多项式,则A(n) = O(n^m).

    • 计算时间复杂度时,可忽略最高和最低的 次幂系数
  • 算法执行时间 = Σ(基本操作(i)的执行次数x基本操作(i)的执行时间)

  • 算法空间复杂度: 算法执行所需空间的增长率

    • S(n) = O(g(n))
    • 若所需额外空间是常数,称"原地工作"
    • 程序本身所占空间
    • 输入数据所占空间
    • 辅助变量所占空间

3.线性表

定义:

  • n(n >= 0)个具有相同类型的数据元素的有限序列

长度:

  • 线性表中数据元素个数

特征:

  • 唯一"第一元素"
  • 唯一"最后元素"
  • 除最后元素,均有唯一后继
  • 出第一元素,均有唯一前驱
  • 线性表的基地址即起始地址

线性表链式存储

任意存储单元存放线性表元素,无连续性(淡化"位序")

  • 便于插入,删除的操作

  • 逻辑相邻,物理未必相邻,即"链式存储"

  • 节点:

    data(数据域)Next(指针域)
  • 单链表:表节点中只包含一个指针域


在这里插入图片描述

  • 头指针: 指向链表第一个节点的指针
  • 头节点: 通常在单链表前加一节点
  • 首节点: 第一个元素节点
  • 尾节点: 最后一个元素节点

查找(按位查找)

  • 删除单链表元素时,只要改前节点指针即可,但要注意释放不用的内存
  • 由于顺序存取结构,为找第i个元素,必须先找到第i-1个元素
template<class T>
    T linklist<T>::GetElem(int i){
        P = Head->next;		//工作指针(首节点),也可头节点
        j = 1;				//计数器,初始为1(首节点),若头节点,为0
       	while(p && j < i){  //顺位工作指针,直至i
            P = P->next;
            j++;
        }
        if(!P || j > i){	//空表或i<0或i>表长
            throw "位置"	  //查找位置不合理
        }else{
            return P->data;
        }
    }						//O(n)

插入

头插法:每次新申请节点放在“头节点”后

template<class T>
    void LinkList <T>::CreatList(int n){
        for(int i = 1;i <= n;i++){
            s = new Node<T>;
            cin>>s->data;
            s->next = head->next
                head->next = s;
        }
    }

尾插法:保证工作指针指向最后节点,方便插入

template<class T>
    void LinkList <T>::CreatList(int n){
        Node <T> *P,*S;			//工作指针,P指向尾节点
        P = Head;
        for(int i =1,i <= n;i++){
            s = new Node<T>;
            cin>>s->data;
            s->next = p->next;	//新节点链插入表尾
            p->next = s;
            p = s;
        }
    }

4.链表

循环链表:终点指针指向head

双向链表

单链中每个节点再设置一个指向其前驱节点的指针域

在这里插入图片描述

  • 空间换时间

静态链表

用数组描述链表,包括:

  • data域:存放数据
  • next域:存放该元素后继所在数组下标
  • 其中0单位的next存放首元素下标

在这里插入图片描述

  • 缺点:

    • 没有解决连续存储分配带来的表长难以确定
    • 其还需要维护一个空闲链
    • 不可随机存储
  • 间接寻址

    • 存储不相邻,但地址存储位置相邻,可随机存取,但仍存在表厂难以确定的情况

5.顺序存储和链式存储

顺序存储

  • 优点:
    • 随机存取
    • 无需为表示逻辑关系占用额外内存(指针)
  • 缺点:
    • 容量要先固定
    • 不方便删除、移动

链式存储

  • 优点:
    • 方便删除、移动
    • 无需先顶容量
  • 缺点:
    • 只可顺序访问
    • 存储密度低

6.栈

在这里插入图片描述

  • 栈顶指向an的上方
  • 后进先出
  • 出入栈要检查上下是否溢出

常用操作

- InitStack(&S)		//初始化
- DestroyStack(&S)	//销毁
- Push(&S,e)			//入栈
- Pop(&S)				//出栈
- GetTop(S)			//获取栈顶元素
- StackEmpty(S)		//测栈空
- ClearStack(&S)		//清空栈

顺序栈

template <Class T>
class SqStack{
    Private:
	    T *base;			//栈底指针
    	int top;			//栈顶
	    int stackSize;		//栈容量
    public:...
}

链栈

不带头结点

template <Class T>
struct Node{
    T data;
    Node<T> *next;
}

顺序栈vs链栈

时间:出入栈均为常数级

时间:

  • 顺序栈:容量受限制
  • 链栈:因指针需要额外存储空间

链栈特点

  • 无栈满问题,空间可扩充
  • 插入与删除仅在栈顶执行
  • 链栈栈顶在链头
  • 适合多栈操作

7.队列

基本操作

- T* base;			//存储空间基址
- int front;		//队头指针
- int rear;			//队尾指针
- queueSize;		//队容量
- InitQueue(&Q)		//初始化
- DestroyQueue(&Q)	//销毁
- GetQueue(Q)		//获取头元素
- EnQueue(&Q,e)		//入队
- DeQueue(&Q,e)		//出队
- QueueEmpty()		//判断队空
- QueueFull()		//判断队满
- ClearQueue();		//清空队列
- QueueTranverse();	//遍历队列

**特点: **

  • 有头空节点
  • 只允许在表的一端进行插入,而在另一端删除元素的线性表
  • 先进先出
  • 假溢出:数组低端根据“先进先出”产生前空闲空间,但后端已满的现象,通过循环队列(头尾相接)解决

链队

仅在表头删除和表尾插入的单链表


循环队列

在这里插入图片描述


循环栈

在这里插入图片描述

8.串相关

概念

  • 串:零或多个字符组成,有限序列,一串字符,即S1S2…Sn
  • 空串:零个字符,即NULL
  • 空格串:空格组成的串
  • 字串:主串中任意连续字符组成
  • 空串是任何串的子串

串匹配

  • 结果:字串第一字符在主串中的位序
  • KMP:仅子串移动,O(n+m)
  • BF:主,子串均多次回溯,最好O(n+m)。最差O(n*m)

9.矩阵压缩存放

类型

  • 对称矩阵:Aij = Aji
  • 三角矩阵:带宽、奇
  • 对角矩阵
  • 稀疏矩阵:e <= 0.05 e = 非零元个数/元素个数
  • 三对角矩阵

10.广义表

  • 数据元素有相对次序
  • 长度:最外层包含元素个数
  • 深度:括号重数
  • 可以是一个递归表,深度无穷,长度有限
  • 可分为
    • 表头Head()=
    • 表尾:Tail() = ( , ,)
  • 表头可为原子或表
  • 表尾一定是表

11.树

  • n个有限数据元素集合
  • n = 0时,为空树
  • 根节点:先祖,无前驱
  • 子树:根节点子树
  • 节点的度:某节点所拥有的子树个数
  • 树的度:树中各节点度的最大值
  • 叶子节点:终端节点,无子代
  • 分支节点:非终端节点
  • 孩子,双亲,兄弟
  • 祖先,后代
  • 路径长度:经过的边数
  • 层数:根节点为1
  • 有序树,无序树:若一棵树中节点子树从左向右有次序,为有序树
  • 森林:树的集合,可谓0
  • Tree = (root,F)

二叉树

根的元素,分叉为左子树,右子树。子树数量<=2(最大二分叉)

满二叉树

  • 叶子只出现在最下一层(深度相同)
  • 度只为0或2

完全二叉树

  • 在满二叉树中,从最后节点开始,连续去任意个节点,即为一颗完全二叉树

平衡二叉树

  • AVL
  • |左子树深度 - 右子树深度| <= 1
  • 平衡因子:左子树高度 - 右子树高度 = -1 or 0 or -1
  • 按中序遍历会是一个从小到大的排列

性质

  • 一棵非空二叉树的第i层上支队2^(i-1)个节点
  • 深度为k的而擦函数中,最多有2^k-1个节点
  • 对于非空二叉树,若叶子节点数n0,度为2的节点度为n2,则n0 = n2 +1
  • 具有n个节点的完全而擦函数的深度为log2n +1
  • 对于具有n个节点而擦函数,编号1~n;对于任意的i
    • if(i > 1),则i的节点的双亲节点序号为(i/2)
    • if(i = 1),则i为根节点
    • if(2i <= n),则i的节点的左孩子节点序号为2i
    • if(2i > n),则i的节点无左孩子
    • if(2i + 1 <= n),则i的节点的右孩子节点序号为2i+1
    • if(2i + 1 > n ),则i的节点无右孩子
  • 二叉树的顺序存储结构一般仅存“完全二叉树”
  • 三叉链表:祖宗节点、左子树、数据、右子树

遍历

  • 先序:根节点访问先后
  • 中序:默认从左至右
  • 后序
  • 层序遍历:第一层开始,逐层访问,从上至下,从左至右

线索二叉树

  • 线索:序列中的第一个(前驱)和后一个(后继)
  • 包含“线索”的存储结构,“线索链表”
  • 若有左孩子,则无前驱指向(二占一)
  • 若有右孩子,则无后继指向(二占一)

赫夫曼(哈夫曼)树

  • 节点路径长度:节点间分支个数
  • 树的路径长度:根到每个节点路径长度和
  • 树的带权路径长度:书中所有叶子节点的带权路径之和WPL
  • WPL最小的二叉树为“最优二叉树”,“哈夫曼树”
  • 权值越大的叶子节点越靠近根节点
  • 只有度为0(叶子)或2(分支)的节点

赫夫曼编码

  • 等长编码:一组对象的二进制位串的长度相等
  • 前缀编码:一组编码中任一编码都不是其他任何一个编码的前缀
    • 保证了解码时不会有多种可能
  • 规定赫夫曼树左分支代表0.右分支为1,从根节点到每个叶子节点所经过的路径组成01序列为叶子编码

树转二叉树

  • 左是孩子,右是兄弟

树遍历

  • 先根遍历:先访问根节点,再依次访问各子树
  • 后根遍历:先访问子树
  • 树不动

森林遍历

  • 先序遍历:先访问森林中第一棵树的根节点,即依次从左至右队森林中每颗树进行先根遍历
  • 中序遍历:依次从左至右队森林中每一颗树进行后根遍历

12.图

  • Graph = (V,E),V表示顶点,E表示边集
  • 无向图,有向图,无向网,有向网

邻接点:

  • 边的两点互为邻接点

有向完全图:

  • 任意两顶点间都有方向互相反的两条弧相连接
  • n(n-1)条边

无向完全图

  • 任意两顶点间只有一条边相连接
  • [n(n-1)]/2条边
  • 稠密图,稀疏图

度:

  • 顶点边数
  • 出度、入度

权:

子图:

  • 完全继承于父图

连通图:

  • 图中任意两点都有路径相连接

连通分量:

  • 非连通图中极大连通子图

强连通图:

  • 任意两顶点间存在一条有向路径

图生成树

  • n个顶点,e条边
  • 其中n个顶点和n-1条边构成一个极小的连通子图为生成树

图的存储

  • 邻阶矩阵
    • A[ i ] [ j ] = 1 (vi,vj)有边
    • A[ i ] [ j ] = 0 (vi,vj)无边
    • 无向图形成矩阵是对称矩阵
    • 矩阵中同一元素行和列”1“的最大量数为度数
    • 网图即代换”1“的值
  • 邻接表
    • 无向图:i的度为边表中节点个数
    • 有向图:节点数为出度数(逆表中为入度)
    • 网图中添加域量赋权

图的遍历

  • 深度优先:栈式(返回)
  • 广度优先:队列式(不返回)

关节点

  • 若一个节点丢失,图出现多个连通分量,则是

重连通图

  • 无关节点

最小生成树

  • 无向连通图生成树不唯一(WPL相同)
  • 有且仅有n-1条边
  • Prim:点扩散式
  • kruskal:小组织连接成大组织

最短路径

  • 一个源点到其余点
  • 此路径上,必定只含一条弧,且权值最小
  • Dijkstra:a-b,a-c,a-d(点->线->面)
  • Floyd:成邻接矩阵,所有可能路径

DAG图

  • 有向无环图

AOV网与拓扑算法

  • 输出入度为0的节点
  • 删除该点与其边
  • 重复

关键路径:

  • 始终点时间最大的路径
  • e[ i ] = l[ i ]的路径
    • e[ i ]活动最早开始时间
    • l[ i ]活动最晚开始时间

13.查找

有序折半查找

  • 有序、顺序存储
  • 流程:
    • 查找值与中间元素关键字比较:
    • 相等则成功
    • 小于则左半区继续折半查找(不包括中点)
    • 大于则右半区
    • T(n) = O(log2n)

哨兵顺序查找

  • T(n) = O(n)

动态查找

  • 又叫树表查找
  • 流程:
    • 用二叉树排序树(BST)
    • 左子树上节点均小于根节点
    • 左子树上节点均大于根节点
    • 左右子树也遵循上述规则
  • 最好Tn = O(log2n)
  • 最坏Tn = O(n)

14.哈希函数

散列函数

特点:

  • 函数简单,速度快
  • 计算出的地址,应在哈希地址集中大致均匀分布
  • 解决冲突方案

常用哈希函数

  • 直接定址
    • Hash(k) = a * k + b
    • 线性哈希
    • 不会发生冲突
  • 除留余数
    • Hash(k) = k mod p
    • p一般选质数
    • 若表长为m,则要求p <= m
    • 一定有冲突
  • 乘余取整
  • 数字分析
  • 平方取中
  • 折叠

处理冲突

  • 开放定址
    • 关键字所得hash地址冲突,则区寻找下一个空的哈希地址
    • 线性:向后探测是否为空
    • 二次探测:12,-12,22,-22···左右平方探测
    • 双哈希:伪随机数列
  • 建立一个公共溢出区
    • 一个基本表
    • 一个溢出表

哈希表查找分析

  • 比较次数取决于产生冲突的多少
  • 冲突产生因素:
    • 哈希函数是否平均
    • 处理冲突的方法
    • 填满因子α = 元素个数/表长
    • 哈希表平均查找长度仅取决于填满因子

15.排序

  • 稳定性:相同关键码元素间位置关系是否受排序影响
  • 内排序(仅在内存)
  • 外排序
  • 单键排序
  • 多键排序
  • 是否基于比较

内排序

  • 插入
    • 直接、折半、表插入、希尔
  • 交换
    • 快速排序、冒泡
  • 选择
    • 简单选择、树形、堆
  • 归并
    • 二路归并

三大经典排序方法

  • 时间复杂度:O(n^2)
  • 空间复杂度:O(1)
  • 均稳定

快速排序

  • 枢轴
  • 左右排形成类似于”树“的结构
  • 时间复杂度:O(nlog2n) ~ O(n^2)
  • 不稳定
  • 最坏情况时就是冒泡排序
  • 辅助存储空间:O(log2n) ~ O(n)

堆排序

  • 定义满足Ki < K2i且Ki < K(2i+1)
  • 或定义满足Ki > K2i且Ki > K(2i+1)
  • 是一种具有完全二叉树的性质:根节点小于孩子节点

16.表达式

前缀表达式

  • 构造树,从右向左取第一个最低级运算作为根节点
  • 左右子树再重复操作

后缀表达式

  • 最近的两数与最近的符号进行运算
  • 重复操作
    hash地址冲突,则区寻找下一个空的哈希地址
    • 线性:向后探测是否为空
    • 二次探测:12,-12,22,-22···左右平方探测
    • 双哈希:伪随机数列
  • 建立一个公共溢出区
    • 一个基本表
    • 一个溢出表

哈希表查找分析

  • 比较次数取决于产生冲突的多少
  • 冲突产生因素:
    • 哈希函数是否平均
    • 处理冲突的方法
    • 填满因子α = 元素个数/表长
    • 哈希表平均查找长度仅取决于填满因子

15.排序

  • 稳定性:相同关键码元素间位置关系是否受排序影响
  • 内排序(仅在内存)
  • 外排序
  • 单键排序
  • 多键排序
  • 是否基于比较

内排序

  • 插入
    • 直接、折半、表插入、希尔
  • 交换
    • 快速排序、冒泡
  • 选择
    • 简单选择、树形、堆
  • 归并
    • 二路归并

三大经典排序方法

  • 时间复杂度:O(n^2)
  • 空间复杂度:O(1)
  • 均稳定

快速排序

  • 枢轴
  • 左右排形成类似于”树“的结构
  • 时间复杂度:O(nlog2n) ~ O(n^2)
  • 不稳定
  • 最坏情况时就是冒泡排序
  • 辅助存储空间:O(log2n) ~ O(n)

堆排序

  • 定义满足Ki < K2i且Ki < K(2i+1)
  • 或定义满足Ki > K2i且Ki > K(2i+1)
  • 是一种具有完全二叉树的性质:根节点小于孩子节点

16.表达式

前缀表达式

  • 构造树,从右向左取第一个最低级运算作为根节点
  • 左右子树再重复操作

后缀表达式

  • 最近的两数与最近的符号进行运算
  • 重复操作
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值