第1章 数据结构绪论
数据结构:是相互之间存在一种或多种特定关系的数据元素的集合。
逻辑结构是面向问题的,而物理结构就是面向计算机的,其基本的目标就是将数据及其逻辑关系存储到计算机的内存中。
逻辑结构:实质是指数据对象中数据元素之间的相互关系。
1.集合结构(没关系)
2.线性结构(一对一)
3.树形结构(一对多)
4.图形结构(多对多)
物理结构:是指数据的逻辑结构在计算机中的存储形式。
1.顺序存储结构:是把数据元素存放在连续的存储单元里,其数据间的逻辑关系和物理关系是一样的。(排队站位)。
顺序存储结构的3个属性:存储空间的起始位置,线性表的最大存储容量,线性表的当前长度。
2.链式存储结构:是把数据元素存放在任意的存储单元里,这组存储单元可以是连续的,也可以是不连续的。(银行拿号排队)。用指针(号)存放数据元素地址,通过地址就可以找到相关联数据元素的位置。
第2章 算法
ps:很遗憾以前没明白“算法是程序的灵魂”这句话......又黑又重又贵的《算法导论》拿来瞻(dian)仰(dong xi)了。
算法:是解决特定问题求解步骤的描述,在计算机中表现为指令的有限序列,并且每条指令表示一个或多个操作。
算法特性:
1.输入输出
2.有穷性
3.确定性
4.可行性
算法设计的要求:
1.正确性
2.可读性
3.健壮性
4.时间效率高
5.存储内存底
常见的时间复杂度:O(1)<O()<O(n)<O(n
)<O(
)<O(
)<O(
)<O(n!)<O(
)
第3章 线性表
线性表(List):零个或多个数据元素的有限序列,得是相同数据类型,一个元素只有一个前驱元素(除第一个)和一个后继(除最后一个)元素。(人根据号码排队,不能用书包给别人占位)。在较复杂的线性表中,一个数据元素可以由若干个数据项组成。(学号,姓名,性别,手机号码,家庭地址)。
线性表的顺序存储结构:指的是用一段地址连续的存储单元一次存储线性表的数据元素。
数组的长度是存放线性表的存储空间的长度,存储分配后这个量一般是不变的。
线性表的长度是线性表中数据元素的个数,随着线性表插入和删除操作的进行,这个量是变化的。
在任意时刻,线性表的长度(来的人数)<数组的长度(占的作为数)
插入:火车站排队买票,如果插队则这个人后面的人都要往后移动。
删除:火车站排队买票,如果有人走了,这个人的后面的人都将往前移动。
线性表的顺序存储结构优点:
1.无须为表示表中元素之间的逻辑关系而增加额外的存储空间
2.可以快速的存取表中任一位置元素
线性表的顺序存储结构缺点:
1.插入和删除操作都需要移动大量元素
2.当线性表长度变化较大时,难以确定存储空间的容量
3.造成存储空间的“碎片”
线性表的链式存储结构:n个节点(ai的存储影像)链结成一个链表,即线性表(a1,a2,a3,......,an)的链式存储结构,因此为此链表的每个节点中只包含一个指针域,所以叫单链表。单链表通过每个节点的指针域将线性表的数据元素按其逻辑次序链接在一起。
节点:由存放数据元素的数据域和存放后继节点地址的指针域组成。
假设p是指向线性表第i个元素的指针:
p->data的值是一个数据元素,即节点ai的数据域。
p->next的值是一个指针,指向i+1个元素,即指向ai+1。
链表中第一个节点的存储位置叫做头指针。头节点(可存线性表+头指针,其数据域一般没什么意义)和第一个节点(第一个元素+指向下一个元素的位置)不一样。最后一个节点(最后一个元素+null)。
3.11单链表
单链表的插入:s->next=p->next;p->next=s。(顺序一定不能反)
单链表的删除:p->next=p->next->next 即 q=p->next;p->next=q->next。
对于插入或者删除数据越频繁的操作,单链表的效率优势越是明显。
3.12静态链表
3.13循环链表
将单链表中终端节点的指针端由空指针改为指向头节点,就使整个单链表形成一个环。
3.14双向链表
在单链表的每个节点中,再设置一个指向其前驱节点的指针域。
第4章 栈与队列
ps:在上完数据结构课程,我就只记得栈和队列这两个,惭愧......
栈是限定仅在表尾(指的是栈顶而不是栈底)进行插入和删除操作的(一种特殊的)线性表(事先确定存储空间大小)。
队列是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。
允许插入和删除的一端称为栈顶(top),另一端称为栈底(button)。不包含任何数据元素的栈称为空栈。栈又称为后进先出(Last In First Out)的线性表。
栈的插入操作:称为进栈,压栈,入栈。
栈的删除操作:称为出栈,弹栈
栈的应用:浏览器上面的后退键,word、photoshop的撤销键。递归。四则运算表达式求值。
递归:一个直接调用自己或者通过一系列调用的语句间接的调用自己的函数称为递归函数。
思考:如何用栈实现队列?两栈共享空间。
栈的顺序存储结构:(和线性表差不多)
栈的链式存储结构:(和线性表差不多)
迭代和递归的区别:迭代使用的是循环结构,递归使用的是选择结构。
逆波兰算法(RPN):不需要括号的后缀表达法。
后缀表达式:所有的符号都是在要运算数字的后面出现的。
将后缀表达式进行运算得出结果(栈用来进出运算的数字):
规则:从左到右遍历表达式的每个数字和符号,遇到数字就进栈,遇到是符号,就将处于栈顶的两个数字出栈,进行运算,运算结果出栈,一直到最终获得结果。
中缀表达式转后缀表达式(栈用来进出运算的符号):
标准四则匀速那表达式叫做中缀表达式。
规则:从左到右遍历中缀表达式的每个数字和符号,若是数字就输出,即成为后缀表达式的一部分;若是符号,则判断其与栈顶符号的优先级,是右括号或优先级不高于栈顶符号(乘除优先加减)则栈顶元素依次出栈并输出,并将当前符号进栈,一直到最终输出后缀表达式为止。
队列是一种先进先出(First In First Out)的的线性表。允许插入的一端称为队尾,允许删除的一端称为队头。
队列的应用:电脑假死的时候,鼠标点了很多下都没有反应,等到电脑活过来了,然后刚才的操作全部执行一遍;显示器上笔记本上的输出。
为了避免当只有一个元素时,队头和队尾重合使处理变得麻烦,所以引入两个指针,front指针指向队头元素,rear指针指向队尾元素的下一个位置,这样当front等于rear时,此队列不是还剩一个元素,而是空队列。
把队列这种头尾相接的顺序存储结构称为循环队列。
队列满的条件:(rear+1)%QueueSize==front
计算队列长度公式:(rear-front+QueueSize)%QueueSize
队列的链式存储结构,其实就是线性表的单链表,只不过它只能尾进头出而已。
第5章 串
串(String)是由零个或多个字符组成的有限序列,又名字符串。
空串和空格串的区别
子串和主串的区别
串的顺序存储结构:是用一组地址连续的存储单元来存储串中的字符序列。按照预定义的大小,为每个定义的串变量分配一个固定长度的存储区。一般是用定长数组来定义。一般用”\0“来表示字符串的终结。
串的链式存储结构:和线性表相似,但由于串结构的特殊性,结构中每个元素数据是一个字符,如果也简单的应用链表存储串值,一个节点对应一个字符,就会浪费很大的空间,因此,一个节点可以存放一个字符,也可以考虑存放多个字符。
朴素的模式匹配算法(效率低)
KMP模式匹配算法(效率高)(看不懂!!!)
移动位数 = 已匹配的字符数 - 对应的部分匹配值
第6章 树
树:数(Tree)是n(n>=0)个节点的有限级。n=0时称为空树。在任意一颗非空树种:(1)有且仅有一个特定的称为跟(Root)的节点;(2)当n>1时,其与节点可分为m(m>0)个互不相交的有限集T1,T2,......,Tm,其中每个集合本身又是一棵树,并且称为根的子树(Sub Tree)。
结点的分类:根节点,内部节点,叶节点或终端节点。
结点间的关系:双亲,兄弟,子孙。
树的存储结构表示法:
1.双亲表示法:假设以一组连续空间存储树的节点,同时在每个节点中,附设一个指示器指示其双亲节点在数组中的位置。
下标 | data:数据域,存储节点的数据信息 | parent:指针域,存储该节点的双亲在数组中的下标 | firstchild |
下标 | data:数据域,存储节点的数据信息 | parent:指针域,存储该节点的双亲在数组中的下标 | rightsib |
2.1孩子表示法(指针域的个数就等于树的度数,取最大度):由于树中每个节点可能有多颗子树,可以考虑多重链表,即每个结点有多个指针域,其中每个指针指向一颗子树的根结点,这个叫多重链表表示法。
缺点:由于各结点的度相差很大时,非常浪费空间。
2.1孩子表示法(每个结点指针域的个数等于该结点的度):
缺点:虽然这种方法克服了浪费空间的缺点,但是由于各个结点的链表是不相同点的结构,加上要维护结点的度的数值,在运算上就会带来时间上的损耗。
2.1双亲孩子表示法(把每个结点的孩子排列起来,以单链表作存储结构,则n个结点有n个孩子链表,如果是叶子结点则此单链表为空。然后n个头指针又组成一个线性表,采用顺序存储结构,存放进一个以为数组中。
child | next |
data | firstchild |
3.孩子兄弟表示法
任意一棵树,它的结点的第一个孩子如果存在就是唯一,它的右兄弟如果存在也是唯一的。因此,我们设置两个指针,分别指向该节点的第一个孩子和此节点的右兄弟。
data | firstchild | rightsib |
二叉树(Birnary Tree):n(n>=0)个结点的有限集合,该集合或者为空集(称为空二叉树),或者由一个根节点和两颗互不相交的,分别称为根结点的左子树和右子树的二叉树组成。
特殊的二叉树:
1.斜树
2.满二叉树
3.完全二叉树
二叉树的顺序存储结构:一般只用于完全二叉树
二叉树的链式存储结构:二叉链表,二叉树每个结点最多有两个孩子,所以为它设置一个数据域和两个指针域。
lchild | data | rchild |
二叉树的遍历:
1.前序遍历
2.中序遍历
3.后序遍历
4.层序遍历
线索二叉树(看不懂):把指向前驱和后继的指针称为线索,加上线索的二叉树表称为线索链表,相应的二叉树就称为线索二叉树(Threaded Binary Tree)。
二叉树线索化:实质上就是将二叉链表中的空指针改为指向前驱或后继的线索。线索化的过程就是在遍历的过程中修改空指针的过程。
数,森林与二叉树之间的转换:
1.树转换为二叉树
2.森林转换为二叉树
3.二叉树转换为树
4.二叉树转换为森林
赫夫曼树及其应用:压缩,赫夫曼编码。
带权路径的二叉树。
第7章 图
对于具有e条边的无向图,它的邻接表中有2e个边结点
第8章 查找
查找表:由同一类型的数据元素(或记录)构成的集合。
关键字:数据元素中某个数据项的值,又称为键值,用它可以标识一个数据元素。也可以标识一个记录的某个数据项(字段),称为关键码。
次关键字:可以标识多个数据元素(或记录)的关键字。
查找:根据给定的某个值,在查找表中确定一个其关键字等于给定值得数据元素(或记录)。
静态查找表(目的仅仅是为了查找):只作查找操作的查找表。
1.查询某个“特定”的数据元素是否在查找表中。
2.检索某个“特定的”数据元素和各种属性。
动态查找表:在查找过程中同时插入查找表不存在的数据元素,或者从查找表中删除已经存在的某个数据元素。
1.查找时插入数据元素。
2.查找时删除数据元素。
8.3 顺序表查找:
一堆书散乱在地上,然后把它们放好后查找。
1.顺序查找又叫线性查找。
2.顺序表查找优化:从尾部查找,避免查找时下标越界。
8.4 有序表查找
1.折半查找
2.插值查找(折半查找的改进):根据查找关键字key与查找表中最大最小记录的关键字比较后的查找方法,其核心:(key-a[low])/(a[high]-a[low])。适用于表长较大,而关键字又分布比较均匀的查找表。不适用分布极端不均匀的查找表。
3.斐波那契查找(看不懂):
斐波那契性质:前一个数除以后一个相邻数字,数值趋向于黄金比例值。
8.5 线性索引查找
数据结构的最终目的是提高数据的处理速度,索引是为了加快查找速度而设计到的一种数据结构。
索引就是把一个关键字与它对应的记录想关联的过程,一个索引由若干个索引项构成,每个索引项至少包含关键字和其对应的记录在存储器中的位置等信息。
索引是组织大型数据库以及磁盘文件的一种重要技术。
索引结构分为:线性索引,树形索引和多级索引。
线性索引:线性索引就是将索引项集合组织为线性结构,也成为索引表。
1.稠密索引:将数据集中的每个记录对应一个索引项,索引项一定是按照关键码有序的排列。
2.分块索引:把数据集的记录分成若干块,并且这些块满足:块内无序,块间有序。
3.倒排索引(看不懂):由属性来确定记录的位置。
8.6 二叉排序树(链式存储)
1.二叉排序树,又称为二叉查找树。它或者是一个空树,或者是具有下列性质的二叉树:
若它的左子树不为空,则左子树上所有结点的值均小于它的根结点的值。
若它的右子树不为空,则右子树上所有结点的值均大于它的根结点的值。
它的左,右子树也分别为二叉排序树。
二叉排序树的插入操作
二叉排序树的删除操作
8.7 平衡二叉树(AVL树)
解决如何让二叉排序树平衡?
平衡二叉树是一种二叉排序树,其中每一个节点的左子树和右子树的高度差至多等于1。是一种高度平衡的二叉排序树。
距离插入结点,且平衡因子的绝对值大于1的结点为根的子树,我们成为最小不平衡子树。
将二叉树上结点的左子树深度减去右子树深度的值称为平衡因子BF,所有结点平衡因子只能是-1,0,1。
8.8 多路查找树(B树)
多路查找树,其每一个结点的孩子数可以多于两个,且每一个结点处可以存储多个元素。
4种特殊形式:
1.2-3树
2.2-3-4树
3.B树
4.B+树
8.9 散列表查找(哈希表)概述
散列技术是在记录的存储位置和它的关键字之间建立一个确定的对应关系f,使得每个关键字key对应的存储位置f(key)。查找时,根据这个确定的对应关系找到给定值key的映射f(key),若查找集合中存在这个记录,则必定在f(key)的位置上。
把f叫做散列函数或者哈希函数。
采用散列技术将记录存储在一块连续的存储空间中,这块连续的存储空间称为散列表或者哈希表。
散列技术既是一种存储方法,也是一种查找方法。
散列技术的记录不存在什么逻辑关系,它只与关键字有关联,散列主要是面向查找的存储结构。
8.10 散列函数的构造方法
1.直接定址法:取关键字的某个线性函数值为散列地址。f(key)=a x key+b (a,b为常数)。
2.数字分析法:适合处理关键字位数比较大的情况。
3.平方取中法:适合处理不知道关键字的分布,而位数又不是很大的情况。
4.折叠法:适合事先不知道关键字的分布,适合关键字位数比较多的情况。
5.除留余数法:
6.随机数法:
8.11 处理散列冲突的方法
1.开放地址发:一旦发生冲突,就去寻找下一个空的散列表地址,只要散列表足够大,空的散列地址总能找到,并将记录存入。
2.再散列函数法
3.链地址发
4.公共溢出区法
哈希表:哈希表是一种根据关键码去寻找值的数据映射结构,该结构通过把关键码映射的位置去寻找存放值的地方。
最典型的的例子就是字典,大家估计小学的时候也用过不少新华字典吧,如果我想要获取“按”字详细信息,我肯定会去根据拼音an去查找 拼音索引(当然也可以是偏旁索引),我们首先去查an在字典的位置,查了一下得到“安”,结果如下。
这过程就是键码映射,在公式里面,就是通过key去查找f(key)。其中,按就是关键字(key),f()就是字典索引,也就是哈希函数,查到的页码4就是哈希值。
第9章 排序
总结:先吐槽一下,优快云博客没有设置行高的功能?不能Table?只能点上方工具栏首行缩进,还是缩3个的?拖到下方然后发现首行工具栏找不着然后再拖大进度条回去,首行工具栏不固定?头大......over
数据结构就是如果放置一堆数据,然后怎么查找它,最大的思考就是怎么最快的查找到想要的数据!
物理结构就是在内存中实际放的位置,逻辑结构就是它们之间的关系。
每个数据结构都有顺序存储结构和链式存储结构。