数据结构与算法

数据传递,传值,传引用,传数组
数据仅使用一次的那个 def ifnotdef endif
c语言结构申明,标准函数malloc,free
各种算法复杂度???
每种数据结构可以写个程序
斐波那契数列的不重复算的算法
非递归及递归方法移盘子
后缀表达式的运算
实现对璇玑图古诗对破解(将各种规则下对应的诗输出出来)
已知一棵二叉树的前序遍历和中序遍历结果,求后序遍历结果(必须知道中序遍历结果,父母结点???)
普里姆算法和克鲁斯卡尔算法
搜索引擎在授权的情况下,记录用户平时的搜索喜好,调整搜索内容优先度,并将用户可能想了解的信息放在前列。。
递归树?


考试:抽象数据类型
图、AOE、关键路径
O(n)、四个码(n),圈中一个杠(n)
三元组表
算法复杂度分析
小根堆
集合中求第k小
求一棵树的最大高度、最长宽度
如何描述一个算法
# 大话数据结构


## 第一章 数据结构绪论
<!--结构:是指各个组成部分相互搭配和排列的方式-->
<!--数据结构:相互之间存在一种或多种特定关系的数据元素的集合-->


### 结构分类
逻辑结构:数据元素中数据之间的关系
   1.集合结构:集合结构中的数据元素除同属一个集合外,它们之间没有其他关系。
   2.线性结构:线性结构中的数据元素之间是一对一的关系。
   3.树形结构:树形结构中的数据元素之间存在一种一对多的层次关系。
   4.图形结构:图形结构中的数据元素是多对多点关系。
*逻辑结构是针对具体问题,是为解决某个问题。*
物理结构(存储结构):是指数据的逻辑结构在计算机中的存储形式。
   顺序存储结构:将数据元素放在**地址连续**的存储单元中。如数组。(存在顺序)
   链式存储结构:(结构时刻在变化,插队、中途离队、头部排队等)把数据元素存放在任意的存储单元中,这组存储单元可以是连续的,也可以是不连续的。用指针存放相邻结点的地址。
*数据的存储结构应正确反映数据远元素之间的逻辑关系。*


### 抽象数据类型(Abstract data Type ADT):是指一个数据模型及定义在该模型上的一组操作。


## 第二章 算法
1.算法是解决特定问题求解步骤的描述,在计算机中表现为指令的有限序列,并且每条指令表示一个或多个操作。
2.算法具有五个基本特性 : 输入输出、有穷性、确定性和可行性。
3.设计算法应该尽量满足时间效率高和存储量低的需求.
4.算法的时间复杂度:
也就是算法的时间量度,记作 T(n)=O(f(n)) 。它表示随问题规模 n 的增大,算法执行时间的增长率和 f(n) 的增长率相同,称作算法的渐近时间复杂度,简称为时间复杂度。 其中 f(n)是问题规模 n 的某个函数。


## 第三章 线性表:0个或多个数据元素的有限*序列*
线性表的每个数据元素的类型都相同。
    顺序存储结构:用一段地址连续的存储单元依次存储      线性表的数据元素。使用一维数组来实现。
我们对每个线性表位置的存入或者读取数据,对于计算机来说都是相等的时间,也就是一个常数,随机存储结构。
    链式存储结构:除了要存数据元素信息(数据域)外,还要存储它的后继元素的存储地址(指针域),指针域中存储的信息称做指针或链。
建立链表:头插法、尾插法
    *静态链表*(游标实现法)不用指针的实现方法:
1.数组的每一个下标对应一个 data 和一个 cur。数据域 data 用于存放数据元素;游标 cur 存放该元素的后继在数组中的下标。
2.我们通常把未被使用的数组元素称为备用链表。数组第一个元素,即下标为0的元素的 cur 存放备用链表的第一个结点的下标;而数组的最后一个元素的 cur 则存放第一个有数值的元素的下标,相当于单链表中的头结点作用。最后一个元素的 cur 设置为0,即下一位值数据为空。
3.将未被使用及已删除的分量用游标链成一个备用的链表。
    循环链表:从任意一个结点出发,访问到链表的全部结点。
将单链表中终端结点的指针端由空指针改为指向头指针。为使空链表与非空链表处理一致,通常要设置一个头结点,额外一个指针指向头结点。(可用于判断循环是否结束)再设置一个尾指针,可用于合并链表。
    双向链表:
    
## 第四章 栈与链表
    一、栈(stack)是限定仅在表尾进行插入和删除操作的线性表,是线性表的特例。
1.*允许插入删除操作的一段称为栈顶(top)*,另一端称为栈底(bottle)。(后进后出线性表)
2.栈的插入(push)操作:进栈、压栈;栈道删除(pop)操作:出栈、弹栈。
*进栈出栈变化形式*3个元素可以有五种进栈出栈次序。
3.栈的顺序存储结构:用数组实现,下标为0端作为栈底,定义一个top变量来指示栈顶元素在数组中的位置。通常将空栈判定条件定为 top等于-1。<!--时间复杂度为O(1)-->
4.栈的共享(用一个数组存储两个栈):数组有两个端点,始端即下标为0处为一个和末端即下标为n-1处为另一个末端。事实上,使用这样的数据结构,通常都是当两个栈的空间需求有相反关系时,也就是一个栈增长时另一个栈在缩短的情况。
5.栈的链式存储结构,简称为链栈:把栈顶放在单链表的头部。即在链表头进行操作。(不存在栈满情况)<!--时间复杂度为O(1)-->
6.栈的应用———递归:把一个直接调用自己或通过一系列的调用语句间接地调用自己的函数,称做递归函数。
每个递归定义必须至少有一个条件,满足递归时不再进行,即不再引用自身而是返回值退出。
(斐波那契数列)递归问题使用栈来存储数据
7.栈的应用———四则运算表达式求值
    困难在于乘除在加减的后面,但是要先运算。先后顺序的判断,数字以及符号的判断。
    后缀(逆波兰表示法)表示法定义(叫后缀的原因是所有的符号都是在与之相关的数字的后面出现):后缀表达式中无括号存在,栈用来存储数字。
    规则:(已经转换为后缀表达式)从左至右遍历表达式的每个数字和符号,遇到数字就进栈,遇到符号,就将处于栈顶两个数字出栈,进行运算,运算结果进栈,一直到最终获得结果。
    中缀表达式转后缀表达式:栈用来存储符号
    规则:从左至右遍历中缀表达式的每个数字和符号,若是数字就输出,即成为后缀表达式的一部分;若是符号,就判断其与栈顶符号的优先级,是右括号或者优先级低于栈顶符号,则栈顶元素依次出栈并输出,并将当前符号进栈,一直到最终输出后缀表达式为止。(遇见右括号时一直弹栈至左括号出栈,继续读取表达式;遇见低于栈顶优先级时弹栈至空)


    二、队列是只允许在一段进行插入操作,而在另一端进行删除操作的线性表。队列是一种先进先出的线性表,简称FIFO。允许插入的一端称为队尾,允许删除的一段称为队头。(排在头的优先出列,最后来的排在队尾)
1.front指针指向队头元素,rear指针指向队尾元素的下一位置。用于出列后只用移动头指针。
2.但是会出现假溢出(数组越界,但是数组中存在空闲位置时),因此使用循环队列。
3.循环队列:队列这种头尾相连的顺序存储结构称为循环队列。
4.判断队列为空或者满的两种方法:设置标志变量flag,队空时flag为0,队满时为1;队满时只保留一个空间元素(头尾指针也可能相差整整一圈)。


1.队列的链式存储结构,其实就是线性表的单链表,只不过它只能尾进头出,我们把它简称为链队列。


循环队列是事先申请好空间,使用期间不释放;链队列每次要进行申请和释放结点,但不存在考虑数组大小的问题。


## 第五章 串
1.串的定义:串(string)是由零个或多个字符组成的有限序列,又名叫字符串。
2.ASCII由7位;扩展ASSIC;Unicode
3.串的顺序存储结构:下标为0或者字符串尾保存串的长度(有的编程语言用“\0”来表示串值的终结),串的存储结构可在程序执行过程中动态分配而得。
4.*朴素的模式匹配算法*:子串的定位操作(在一篇文章中找一个单词)假如在主串“goodgoogle”中,找到“google”这个子串的位置。
    挨个字符匹配(将主串的每一个字符作为子串开头)的话就极大提高了时间复杂度。
5.*KMP模式匹配算法*:T="abcdex" S="abcdefgab"
    KMP算法关键:如果我们知道T串中首字符“a”与后面的串“bcdex”中任意一个字符都不相等,那么就可以直接跳过相同位置“bcde”位置的比较,直接与“f”开始比较(由第一次比较知“f”之前的字符都匹配)。
    
    ??????????????????????5.7
    KMP算法就是为了让没必要的回溯不发生。(即主串的核对的字符位置下标会再返回到这次比较的首字符的下一个字符进行比较,考虑子串*T的首字符与后面字符的比较,发现有相等字符时,子串下标j的变化就会不同,也就是说 j 值的变化只取决于T串的结构中是否有重复*的问题。)
    j的值是子串中与首字符相同字符的位置(首位为1)。
    我们将T串各个位置的j值的变化定义为一个数组next,那么next的长度就是T串的长度。
    
定义:
            |0 ---当j=1时(即没重复时?)
next[j] =   |Max{k|1<k<j,且首字符在子串中存在相同的字符}此集合不空时
            |1  其他情况
    next数组值推导
    我们根据经验得到如果前后缀一个字符相等,k值是2,两个字符k值是3,n个字符k值就是n+1.
?????????????????????????


6.EP算法(KMP算法的改进)


第六章 树(一对多)
1.树的定义:
2.根结点唯一;子树不相交。
3.结点拥有的子树数称为结点的*度*(结点对的 多 的数目);叶;内部结点;
4.结点的*祖先*是从根到该结点所经分支上的所有结点。
5.树中结点的最大层次称为树的深度(Depth)或高度。
6.有序树:各子树从左至右是有顺序的,不能互换的。
7.森林是m棵互不相交的树的集合。
8.树的存储结构:
双亲表示法:每个结点中,data存储结点的数据信息,附设一个指示器parent指示其双亲结点到链表中的位置。
*一个存储结构设计得是否合理,取决于基于该存储结构的运算是否合适、是否方便、时间复杂度好不好等*
孩子表示法(多重链表表示法):每个结点有多个指针域...
孩子兄弟表示法:


9.二叉树
定义:左子树、右子树
满二叉树:所有分支结点都存在左子树和右子树,并且所有叶子都在同一层上。
完全二叉树:对二叉树按层序从左至右编号,若编号为i的结点与同样深度的满二叉树中编号为i的结点在二叉树中位置完全相同。(满足按层序从左至右遍历时无空缺)
完全二叉树的特点:


二叉树的性质:
性质1:在二叉树的第i层上至多有2^(i-1)个结点。
性质2:深度为k的二叉树至多有2^k-1个结点
性质3:任何一个二叉树,若其终端结点数为n0,度为2的结点数为n2,则n0=n2+1。
性质4:具有n
性质5:


二叉树的存储结构:
顺序存储结构:对于完全二叉树的编号顺序来用一维数组来存储。
链式存储结构:
二叉链表:一个数据域两个指针域


二叉树的遍历是指从根结点出发,按照某种*次序*依次*访问*二叉树中所有结点,使得每个结点被访问一次且仅被访问一次。
二叉树遍历方法:(都是针对根结点来考虑的)
1.前序遍历
2.中序遍历
3.后序遍历
4.层序遍历


使用遍历方法建立二叉树


线索二叉树:在空地址处存放指向结点在某种遍历次序下的前驱和后继结点的地址。我们把这种指向前驱和后继的指针称为线索。
线索化二叉树,等于是双向链表
线索化:


树转换为二叉树:加线;去线;层次调整
森林转换为二叉树:
二叉树转换为树:
二叉树转换为森林:
树与森林的遍历:


赫夫曼树及其应用
最基本的压缩编码方法———赫夫曼编码
路径长度:从树中一个结点到另一个结点之间的分支构成两个结点之间的路径,*路径上的分支数目*称做路径长度
树的路径长度就是从树根到每一结点的路径长度之和。
赫夫曼树(最优二叉树):带权路径长度WPL最小的二叉树称做赫夫曼树。
结点的带权的路径长度为从该结点到树根之间的 路径长度 与 结点上权 的乘积。
树的带权路径长度为树中所有叶子结点的带权路径长度之和。
*权重仅存在于叶结点至它的父母???或者说这就是叶到根到权重???*
构建赫夫曼树的赫夫曼算法:
赫夫曼树编码:(根据字符出现的频率,频率高的使其路径长度短,即在树的头几层)


![Screen Shot 2017-12-12 at 7.13.36 P](media/15127937091864/Screen%20Shot%202017-12-12%20at%207.13.36%20PM.png)


???所以要设置长短不等的编码,则必须是任一字符的编码都不是另一个字符的编码的前缀,这种编码称做前缀编码。
发送方和接收方必须要约定好同样的赫夫曼编码规则。


第七章 图
1.图的定义:图是由顶点的有穷非空集合和顶点之间的边的集合组成,
2.,,图中的数据元素称之为顶点,顶点之间的逻辑关系用边来表示。
3.各种图的定义:
简单图:在无向图中,如果任意两个顶点之间都存在边,则称该图为无向完全图。
有向完全图:在有向图中,如果任意两个顶点之间都存在方向相互相反的两条弧的图。
权:与图的边或弧相关的数
网:带权的图
出度入度
连通图:图中任意两顶点都是连同的(直接间接都行)
连通分量
强连通图
强连通分量
连通图的生成树:


图的存储结构:
图的邻接矩阵来表示图(两个数组)
用邻接矩阵来实现图的创建
邻接表(结构+指针)
十字链表(结合上面两个)
邻接多重表


图的遍历
深度优先遍历(DFS)递归???树的前序遍历???
广度优先遍历(BFS)类似于树的层序遍历


最小生成树:构造连通网的最小代价 生成树
普里姆算法:任意选择一个顶点加入集合,找到与它代价最小的边并将这个顶点加入集合,重复添加代价最小的边的顶点,直至添加完所有的顶点。算法复杂度O(n^2)
克鲁斯卡尔算法:选择代价最小的边(该边依附的顶点在不同的连接分量上,即不会形成回路)加入到集合中。算法复杂度O(nlog2n)


最短路径
迪杰斯特拉算法:
弗洛伊德算法:


有向无环图
拓扑排序:
关键路径:


第八章 查找
查找概论:查找表;关键字
顺序表查找:按照线性表记录顺序,逐个进行关键字比对。
有序表查找:
1.折半查找(二分查找):前提是关键码有序,每次与中间值比较大小。时间复杂度为O(log2n)
2.插值查找
4.斐波那契查找:
线性索引查找:
1.稠密索引:每个数据对应一个索引项
2.分块索引:把数据集的记录分成了若干块,对于分块有序的数据集,将每块对应一个索引项
3.倒排索引:(搜索引擎)用属性值确定记录的位置。查找具有该关键字的信息,再排列出信息对应的地址。


二叉排序树(二叉查找树):对有序线性表插入和删除效率不错同时,又可以比较高效率地实现查找的算法。


平衡二叉树(AVL树):是一种二叉排序树,其中每一个结点的左子树和右子树的高度差至多等于1。


多路查找树(B树):2-3树;B树;B+树;


散列表查找(哈希表):散列技术是在记录的存储位置和它的关键字之间建立一个确定的对应关系f,使得每个关键字key对应一个存储位置f(key)。
我们把这种对应关系f称之为散列函数,又称哈希函数。采用散列技术将记录存储在一块连续的存储空间中,这块连续存储空间称为散列表或哈希表。


散列函数的构造方法:
直接定址法:(用年龄关键字作为地址)
数字分析法:(抽取手机后四位作为散列地址)


处理散列冲突的方法


第九章 排序
排序的稳定性:假设ki=kj,且在排序前的序列中ri领先于rj(即i<j),若排序后ri仍就领先rj,则所用排序方法为稳定,否则排序方法为不稳定。


外排序和内排序
影响内排的3个方面:
时间性能:关键字比较次数和记录移动次数
辅助空间
算法复杂性


冒泡排序:两两比较相邻记录的关键字,如果反序则交换。时间复杂度O(n^2)
1.交换排序:确定第一位,第二位。。。。。
2.正宗冒泡:较小的数一步步交换至头部(如同气泡般慢慢浮到上面)
3.冒泡优化:在剩余的已经被判断过的基础上加上标记变量。


简单选择排序:排序时找到合适的关键字再做交换,并且只移动一次就完成相应关键字的排序定位工作。
通过n-i次关键字的比较
时间复杂度O(n^2)


直接插入排序:插入到已排好序的有序表中
时间复杂度O(n^2)


分隔待排序记录的目的是减少待排序记录的个数,并使整个序列向基本有序(小的关键字基本在前面,大的基本在后面)发展。
方法:采用跳跃分割的策略
希尔排序(第一批突破算法复杂度为O(n^2)):相隔某个“增量”的记录组成一个子序列,“增量”的选取:
不稳定,时间复杂度O(n^3/2)


堆排序:时间复杂度O(nlog2n),充分利用完全二叉树深度是   的特性。
每次在选择到最小记录的同时,并根据比较结果对其他记录作出相应的调整(简单选择排序的优化)
堆的定义:堆是具有下列性质的*完全二叉树*:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆。


归并排序:两两 合并 排序
时间复杂度O(nlog2n)
非递归实现归并排序


快速排序(冒泡的升级,属于交换排序类):通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续排序,以达到整个序列有序的目的。
时间复杂度O(nlog2n)
快排的优化

![Screen Shot 2017-12-13 at 12.41.59 A](media/15127937091864/Screen%20Shot%202017-12-13%20at%2012.41.59%20AM.png)


阅读更多 登录后自动展开
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页