数据结果与算法(JAVA版)—重点总概
##第一章 绪论
###1.1基本概念:
-
数据存储结构分为:顺序结构、链接结构、散列结构和索引结构。
-
数据:利用文字符号、数字符号以及其他规定的符号对现实世界实物及其活动所做的抽象描述。
-
数据元素:一个数据整体中可以标识和访问的数据单元。
-
数据记录:数据处理领域组织数据的基本单位,数据中的每个数据元素在许多应用场合被组织成记录的结构。数据项、关键项,关键字。
-
数据结构:数据及其相互间的联系(逻辑关系)。逻辑结构:集合结构、线性结构、树形结构、图形结构。
-
数据类型:对数据的取值范围、每个数据的结构以及允许施加运算的一种定义。简单类型、结构类型。型和值。实例。
-
抽象数据类型:由一组数据和该数据上的操作集所组成。
-
数据对象:数据类型的具体实例。
-
算法:解决特定问题的思路和方法。
-
算法5个特性:
1.有穷性:算法执行步骤有限
2.确定性:算法每一步有明确含义,无二义性
3.可行性:算法每一步可行、可通过手工活机器有效操作在有限时间类完成
4.输入性:算法执行前可以有0个1个或多个输入量
5.输出性:算法执行结束有输出量
###1.2算法描述 -
一个算法可以借助各种不同的工具和手段加以描述。
###1.3算法评价 -
根据评价算法的一般指标,评价出一个具体算法的优劣程度。
-
5个性能指标:
1.正确性:设计评价一个算法的首要指标,在合理的数据输入下,能够在有限的运行时间内得出正确的结果。
2.健壮性:算法对不合理数据输入的反应和处理能力。
3.可读性:算法可以供人们阅读和理解的容易程度。
4.时间复杂度:又叫计算复杂度,算法有效性量度之一。一个算法运行时间的相对量度。此处即算法执行简单操作(如赋值、比较、简单计算、转向、返回等)的次数。比如下面一段求和运算:public int getSum(int[] arr){ int sum=0; for(int i=0;i<arr.length;i++){ sum+=arr[i]; } return sum; }
简单分析,输入为一个数组,比如长度为n,那么算法的运算次数必然与n有关系。第一条和第三条语句都各执行一次简单操作,第二条for循环如下:
int i=0; //1次
m1:if(i>=arr.length) goto m2; //n+1次
s+=b[i]; //n次
i++; //n次
goto m1; //n次
m2:return sum; //n次
总共需要为f(n)=4n+4;即以下表示的O(n)—结果只含有n的一次方的函数。
算法的时间复杂度通常有O(1)、O(n)、O(log2 N)、O(n*log2 N),O(n2)、O(n3)、O(2^n)和O(n!)等形式。O(1)表示算法的运行时间为常量,它不随数据量n的改变而改变。如访问任何数据表中的第一个元素时,无论该表的大小如何,其时间复杂度均为O(1)。具有O(n)数量级的算法被称为线性算法,其运行时间与数据量的大小n成正比。如对一个数据表进行顺序查找时,其时间复杂度就是O(n)。有一些算法的时间复杂度均为O(log2 N),即与n的对数成正比,如在有序表上进行二分查找的算法就是如此。对数字进行各种排序的各种简单算法为O(n^2)数量级,当n加倍时其运行时间将增长4倍;对数组进行排序的各种改进算法为 O(n *log2 N)数量级的。
5.空间复杂度:对一个算法在运行过程中临时占用存储空间大小的量度,衡量算法有效性的一个重要指标。
算法的时间复杂度和空间复杂度通常用数量级的形式表示出来。数量级有常量级、对数级、线性级、线性乘对数级、平方级、立方级、指数级、阶乘级等。
##第二章 集合
###2.1集合定义及运算
###2.2集合的顺序存储结构和操作实现
###2.3集合的链接存储结构和操作实现
-
集合是能够通过值或关键字相互区别的、具有相同类型的一组数据(对象),数据之间不考虑存在任何联系,他们可以按任何次序排列。
-
对集合可以进行多种运算,如添加元素、查找元素、删除元素、集合并运算、集合交运算等,这些运算可以在集合接口类中定义。
-
存储一个集合时,可以采用任一种存储结构,即顺序、链接、索引、散列等存储结构。
-
采用顺序存储结构(ArrayList)存储一个集合时需要定义相应的类,该类中的成员域应包括一个数组对象和一个长度变量,成员方法应该覆盖集合接口类中声明的所有方法,还要带有相应的构造方法。在顺序集合中,集合元素按照数组的下标位置依次存储。
-
采用链接存储结构(LinkedList)存储一个集合时也需要定义相应的类,还需要定义节点类。在链接集合类中,应包括存储集合的单链表的表头指针和长度变量,该类的成员方法也应该覆盖集合接口类中声明的所有方法,还要带有自己的构造方法。在链接集合中,集合元素按照节点之间的链接关系依次存储。当访问一个链接集合时,只能从表头指针开始依次访问每一个节点,不能像顺序存储的集合那样,可以按下标位置直接访问任一个元素。
-
向顺序存储表示的集合中添加元素应直接添加到表尾,向链接存储表示的集合中添加元素应把相应节点添加到表头或表尾。从顺序表示的集合中删除元素只要表尾元素填补到被删除元素的位置即可,从链接表示的集合中删除元素只要把后继节点链接到它的前驱节点即可。
-
集合是一种数据结构,对任一种数据结构进行运算时,都要首先定义出抽象数据类型,据此定义出相应的抽象接口类,进而定义出相应的、采用一种存储结构的实现类,如顺序存储的实现类或链接存储的实现类,在显示类中要定义出接口类中的所有方法,每种方法要追求较优的时间复杂度和空间复杂度。
##第三章 线性表
###3.1线性表的定义和运算
###3.2线性表的顺序存储和操作实现
###3.3有序线性表的定义和实现
###3.4链接存储的一般概念和方法
###3.5线性表的链接存储和操作实现
###3.6有序线性表的链接存储和操作实现
###3.7多项式计算
###3.8稀疏矩阵 -
线性表就是具有线性结构的数据序列,在线性表的抽象数据类型和相应的接口类中,给出了对线性表进行各种运算的方法声明,可以根据实际需要增加和减少这些方法。
-
线性表可以采用数组进行顺序存储,也可以采用结点的链接方式进行链接存储。在链接存储时,所选用的链接表,可以是单链表,也可以是双向链表,在每种链表中可以带有附加表头结点,可以使用首尾相连的循环链接。
-
在采用顺序存储结构实现的线性表中,能够直接访问任何给定位置上的元素,其时间复杂度为O(1),但在采用链接存储结构实现的线性表中,不能够直接访问任何给定位置上的元素,它必须从表头指针开始依次访问前面的所有元素后,才能够取到该元素,其时间复杂度为O(n),n为线性表的长度。
-
在顺序存储的线性表中插入或删除任何给定位置上的元素时,都要平局移动约半个表的元素,所以其时间复杂度为O(n),从链接存储的线性表中插入或删除任何给定位置上的元素时,为查找该位置需要平局比较约半个表的元素(结点),但插入或删除结点的操作,不需要移动任何元素,只需要做好前后结点的链接即可,其时间复杂度为O(1)。
-
在顺序存储的线性表尾插入或删除元素时不需要移动任何元素,其运算的时间复杂度为O(1),在链接存储的线性表的表头插入或删除元素(结点)时不需要为查找位置而访问任何结点,其运算的时间复杂度也为O(1);相反,在顺序表的表头和链接表的表尾做这些运算时,需要花费的时间最长,其运算的时间复杂度为O(n),n为线性表的长度。
-
有序线性表的所有元素必须按照元素值(关键字)的从小到大次序排列,它继承于线性表,并且又定义有自己的按照元素值(关键字)进行插入、删除和查找的方法。它可以继承顺序存储的线性表,也可以继承链接存储的线性表。
-
多项式的计算和表示是线性表的一种典型应用。
-
稀疏矩阵的表示和运算是线性表的又一种典型应用,它比利用二维数组存储稀疏矩阵和运算要节省存储空间和运算时间。
##第四章 栈和队列
###4.1栈的定义和运算
###4.2栈的顺序存储结构和操作实现
###4.3栈的链接存储结构和操作实现
###4.4栈的简单应用举例
###4.5栈与递归
###4.6算数表达式的计算
###4.7队列 -
栈是一种运算受限的线性表,它只允许在栈顶进行插入和删除等运算,各种运算的时间复杂度均为O(1)。
-
栈也适合采用顺序和链接这两种存储结构,通过栈顶指针可以访问到栈顶元素和进行插入、删除的操作。
-
计算机执行递归算法时需要自动建立和使用一个系统栈,用来存储每次调用后的返回地址,形参变量和局部变量的值,每结束一次调用都要按栈中保存的返回地址返回到调用位置向下执行,并自动做一次退栈处理操作。
-
队列是只允许在一端插入,而在另一端删除元素的线性表,进行插入的一端叫做队尾,而进行删除的一端叫做队首,插入和删除的时间复杂度均为O(1)。
-
队列也适合采用顺序和链接这两种存储结构,在顺序队列中,存储空间是首尾相接的一个环,故称为循环队列。若用于存储队列的数组空间大小为n,则在不设定队列长度变量的情况下,其所存队列的最大长度为n-1。
-
在顺序队列中,若队尾指针落后于队首指针一个元素位置,则表示队满;若队首指针与队尾指针相同,则表示队空。
-
栈和队列是线性数据结构中运算最简单的数据结构,但又是最有用的数据结构,它普遍应用于各种算法的实现之中。特别是递归算法的执行过程是依赖栈这种数据结构来实现的。
-
递归是分析问题和解决问题的一种非常重要的方法和手段,很多复杂的问题都可以通过递归迎刃而解。递归过程是采用本身的方法并逐渐向下简化的过程,最终简化到能够直接得到结果,而后逐渐返回依次向上消除递归,最终消除所有递归结束整个算法执行。
-
表达式的计算是栈的一种典型应用,中缀转后缀时需要使用运算符栈,后缀求值时需要使用操作数栈。
##第五章 树和二叉树
###5.1树的概念
###5.2二叉树
###5.3二叉树遍历
###5.4二叉树其他运算
###5.5二叉树搜索
###5.6堆 -
树是一种层次数据结构,若不为空的话,第一层只有一个结点,称为树根结点,其后每一层都是上一层相应结点的后继结点,每个结点可以有任意多个后继结点,但除树根结点外,每个结点有并且只能有一个前驱结点。树中结点的前驱结点称为该结点的父亲或双亲,后继结点称为该结点的孩子。
-
二叉树是度为2的有序树,每个结点至多有两个孩子,其中一个称为左孩子,另一个称为右孩子。若一个结点没有左孩子或右孩子,也可以说该孩子为空。
-
一课深度为h的二叉树,至少含有h个结点,最多含有2^h-1个结点;一课具有n个结点的二叉树,其最小深度为[log2(n+1)],也可以表示为[log2 n]+1。
-
二叉树具有顺序和链接两种存储结构,对于完全二叉树通常采用顺序存储结构,对于普通二叉树通常采用链接存储结构。二叉树链接存储的结点类型用BTreeNode表示,它包含有值域element,指向左孩子结点的指针域left和指向右孩子结点的指针域right。
-
遍历是二叉树的主要运算,它包括先序,中序,后序和层次4种不同的遍历次序,前3种通过递归算法实现,后一种层次遍历通过使用队列的非递归算法实现。每一种遍历算法的时间复杂度均为O(n),n为二叉树中的结点数。
-
对二叉树的其他运算,通常也是在对二叉树递归遍历运算的基础上经适当修改后而得到的,可以根据需要编写出任何对二叉树进行运算的算法。
-
对二叉搜索树进行中遍历得到的结点序列是一个按值从大到小排列的有序序列。
-
对二叉搜索树进行的基本运算是查找,次查找使一个二分查找过程,它首先访问根节点,若其值等于给定值则查找成功,否则当给定值小于根节点值时继续向左子树查找,大于根节点值时继续向右子树查找,直到查找成功或碰到空子树为止。对于一般的二叉搜索树,其查找运算的时间复杂度大致为O(log2 N)。
-
堆是一种满足一定条件的完全二叉树,对于小根堆,它的每个分支结点的值都小于等于孩子结点的值;对于大根堆,它的每个分支结点的值都大于等于孩子结点的值。
-
堆的插入运算是把新元素插入到堆尾,堆的删除操作是删除堆顶元素并把堆尾元素移至堆顶。插入和删除一个元素都要进行堆的调整,使之成为一个新堆,该堆比原堆相应增加或减少了一个元素,调整过程不涉及到所有结点,只涉及到相关的结点。堆的插入和删除运算的时间复杂度为O(log2 N),空间复杂度为O(1)。
##第六章 图
###6.1图的概念
###6.2图的存储结构
###6.3图的抽象数据类型和接口类
###6.4图的邻接矩阵和邻接表存储类
###6.5图的遍历
###6.6对图的其他运算的算法
###6.7图的生成树和最小生成树 -
图结构中的每个结点可以有任意多个前驱和任意多个后继。对于无向图,每个顶点的邻接点即是它的前驱结点;对于有向图,每个顶点的入边邻接点是它的前驱结点,出边邻接点是它的后继结点。
-
无向图中每个顶点的度、入度和出度均等于它的邻接点数;有向图中每个顶点的度、入度和出度分别等于它的邻接点数、入边数和出边数。
-
图的存储包括存储图的顶点信息和边的信息(即顶点之间的关系)两个方面,为了运算方便,通常把他们分开存储。对于图的顶点信息适合采用能够直接存取的数组存储,对于图中边集的信息,主要有邻接矩阵、邻接表和边集数组这3种存储结构表示。
-
对于一个具有n个顶点和e条边的图,它的邻接矩阵是一个n*n阶方阵,无向图中的每条边对应邻接矩阵中的两个对称元素,有向图中的每条边对应邻接矩阵中的一个元素。图的邻接矩阵中主对角线上的元素为0.无向图的邻接矩阵是对称矩阵。
-
图的邻接表是对图中每个顶点建立边结点单链表并把它们的表头指针用一维数组存储起来的一种存储结构。图的边集数组是把图中的每条边作为元素存储到一维数组中的一种存储结构。
-
图的3种存储结构对应3种存储类,此处只介绍了邻接矩阵和邻接表所对应的存储类,没有介绍边集数组所对应的存储类。
-
对图的遍历包括深度优先搜索和广度优先搜索这两种不同的访问顶点次序的方法。对于用邻接矩阵表示的图,从某一顶点出发按某种搜索方法得到的顶点序列是唯一的。对于用邻接表表示的图,从某一顶点出发按某种搜索方法得到的顶点序列随建立的邻接表的不同而可能不同。
-
一个连通图(无向带权图)的生成树含有该图的全部n个顶点和其中的n-1条边,其中权值最小的生成树被称为最小生成树。通过普里姆算法和克鲁斯卡尔算法能够求出一个图的最小生成树m,推荐使用克鲁斯卡尔算法,简单方便快速有效。
##第七章 查找
###7.1查找的基本概念
###7.2二分查找
###7.3索引查找
###7.4散列查找
###7.5B树查找 -
顺序查找即适应于顺序表,也适应于单链表,并且对表中元素的排列次序无要求。顺序查找的时间复杂度为O(n),平均查找长度为(n+1)/2。
-
二分查找只适应于顺序存储的有序表,不适应于单链表。二分查找的时间复杂度为O(log2 N)。二分查找的判定树即是一棵二叉搜索树,又是一棵理想平衡树,查找任一元素的过程对应该树中从树根对应结点的一条路径。二分查找的平均查找长度等于判定树中所有结点的层数之和的平均值。
-
索引查找包括查找索引表和查找子表两个阶段。若索引表的长度为m,每个子表的长度为s,并假定采用顺序方法查找索引表和相应子表,则平均查找长度为1+(m+s)/2。
-
索引表分为稠密索引和稀疏索引两种,在稠密索引中每个索引项对应下一级表中的一条索引项或记录,在稀疏索引中每个索引项对应下一级表中的多条索引项或记录。在实际应用中,当主表(即原始数据记录表)很大时,可以建立多级索引。
-
散列存储是根据元素的关键字计算存储地址的一种存储方法,此地址称为散列地址,用于计算地址的函数称为散列函数,用于存储元素的数组或文件称为散列表。
-
待散列存储的数据集中的元素个数n与散列表长度m的比值称为散列表的装填因子,用a表示,它等于n/m。在利用开放定址法处理冲突的散列存储中,a必须小于等于1,在利用链接法处理冲突的散列存储中,a既可以小于等于1,也可以大于1。
-
在散列存储中,所选的散列函数要尽量使元素的存储地址均匀地分布到整个散列存储的地址空间上,常用的散列函数采用出留余数法构成。
-
散列查找的平均查找长度等于查找全部元素的查找长度之和除以所有元素的个数,它通常比采用其他查找方法得到的查找长度要小得多。
-
在一棵m阶B_树中,所有叶子结点都处在同一层上。在所有的结点中,树根结点至少具有一个关键字和两颗子树,至多具有m-1个关键字和m棵子树;非树根结点至少具有[m/2]-1个关键字和[m/2]棵子树,至多具有m-1个关键字和m棵子树。
-
在B_ 树上插入关键字可以引起结点分裂,在B_树上删除关键字可以引起结点合并,它们是最终引起树的高度增加1或减少1的唯一途径。
##第八章 排序
###8.1排序的基本概念
###8.2插入排序
###8.3选择排序
###8.4交换排序
###8.5归并排序
###8.6外排序 -
直接插入排序、直接选择排序和气泡排序都是简单的排序方法,它们的时间复杂度均为O(n^2),空间复杂度均为O(1)。从稳定性上看,直接插入排序是稳定的,直接选择排序和气泡排序不是稳定的。
-
堆排序、快速排序和归并排序是3种较快的排序方法,它们的时间复杂度均为O(nlog2 N),空间复杂度分别为O(1),O(log2 N)和O(n)。通常情况下,快速排序比堆排序和归并排序要快。
-
对n个元素进行堆排序的过程包括建立初始堆和利用堆排序两个阶段。建立初始堆就是按照编号从大到小依次对每个分支结点进行筛运算,共需进行n/2次筛运算;利用堆排序需要依次对堆顶元素进行n-1次筛运算,每次堆的大小为n-i(1<=i<=n-1),在每次筛运算前都要交换筛顶与堆尾元素。
-
对n个元素进行快速排序是一个递归过程,每次执行一次这个过程就是把当前区间上的所有元素按基准元素划分为前后两个子区间,当一个人子区间的元素个数等于或大于2时继续向下递归。
-
在快速排序中进行一次划分时,通常以该区间上的第一个元素作为基准元素,从第二元素起依次向后扫描,当被扫描元素大于等于基准元素为止,再从最后一个元素起依次向前扫描,当被扫描元素小于等于基准元素时止,接着对调这两个位置上的元素,然后再继续从两边向中间扫描并交换,直到扫描过程相遇为止,把基准元素对调到相遇位置就完成了一次划分。
-
归并排序是两两有序表依次归并的过程,第一趟归并时,有序表的长度为1,即每个元素为一个有序表,归并结果得到的每个有序表的长度为2,当然最后一个有序表可能小于2;第二趟归并时,有序表的长度为2,得到长度为4的有序表,以此类推,直到得到的有序表长度大于等于待排序元素个数n为止。归并排序方法同样适应于外存文件排序。
-
外排序就是对外存文件进行排序,外存文件可以存储在磁盘、光盘和磁带上,但排序方法都是二路或多路归并排序,在排序过程中对文件进行顺序访问(读写)。每访问一次外存,将存取一块的信息(通常为4KB)到内存的文件读/写缓存区内,每次读取文件首先从文件缓存区内读取,若没有再访问一次外存,读取到对应的一个信息块;每次写入文件首先写入到文件写缓存区内,待缓冲区满后再一次写入到外存文件中。进行文件的顺序访问能够最大限度的减少访问外存的次数,提高外存文件的排序速度。
-
对文件进行归并排序,首先要读取原始数据文件,利用内排序方法依次建立初始归并段,并把他们依次交替写入到另外的两个数据文件中;然后通过读取和归并两个数据文件中的对应归并段,交替写入到保存一次归并结果的两个目的文件中,再读取和归并这两个目的文件到两个数据文件中,循环反复,直到归并段大于等于原始文件中的记录个数为止。
放假期间,初略的看完了这本<数据结构与算法>一书,由于不是计算机专业的人,在校并没有学习过该门课程,既然走进了这一行,这本书我想是必须学习了解的。从前往后模糊的看了几天,仅知道个大概,深入不敢讲,概念能瞎比比了。而对于用的最多问的最多的排序算法,书中写的也不是很完善,想深入了解只能看看其他的资料了。