数据结构与算法学习之路(java语言)一

  本文是本人在学习过程中的一些笔记,如有错误请见谅。

一、引论

  学习数据结构和算法需要离散数学以及程序设计个一些概念作为支柱,我认为算法的设计更像是数学模型的搭建,我们需要在搭建过程中考虑运行性能和近乎所有会出现的状况。

  以下的笔记主要出自《数据结构与算法分析》机械工业出版社,我总觉得这本书更适合用于大学的教材,有一些语言翻译以及对象描述晦涩难懂,没有专业基础的看了也只会是一知半解。

  先来说一下递归吧,因为递归在算法中的使用频率非常高,而且也是高级算法的基础。

  递归的简要特性说明:

    当一个函数用自己来定义时就称之为递归。虽然java允许函数是递归的,但是对于数值的计算来说并不是很适合,java提供的仅仅只是遵循递归思想的一种尝试,不是所有的数学递归函数都能被有效的由java的递    归来模拟实现。

    在设计递归方法时,优先考虑基准情形(即方法的出口),再进行递归调用。

    递归调用并不是循环推理,它一定会朝着一个基准情形无限推进。

    递归过程所有递归调用都要能够运行,考虑这一基本法则时结合数学中的归纳法。

    再求解一个问题的同时,切勿在不同递归调用中做重复性的工作。

二、算法分析

  说到算法就一定会有好坏之分,那么怎么区分算法的好坏呢?这里会引入两个概念,时间复杂度和空间复杂度。

  当有一个算法需要估算时间复杂度,我们一般会以最坏情况为标准去估算时间,因此复杂度也一样会抛弃低阶计算一个上界O。实际上分析的结果为程序在一定时间范围内能够终止提供了保障,程序可能提前结束但是  绝不可能错后。

  下面是一个简单的for循环例子:

  

1 public static int sum(int n) {
2         int partiaSum;
3     
4         partiaSum = 0;
5         for (int i = 1; i <= n; i++) {
6             partiaSum += i*i*i;
7         }
8         return partiaSum;
9     }    

 

 

  这个算法计算∑i^3,那么要计算时间复杂度,首先所有的声明不计时间,第4行和第8行各占一个时间单位,第6行每执行一次占用4个时间单位会进行两次乘法,一次加法和一次赋值,执行n次共使用4n个时间单位,第5行在初始化i、测试i<=n和对i自增存在开销,初始化1个,测试为n+1个,自增为n个共2n+2个时间单位,我们忽略调用方法和返回值的开销,得到总量为6n+4个时间单位。因此我们说该方法时间复杂度为O(N)。空间复杂度则可以看此算法所创建的变量数量,这里为两个变量partiaSum和i。

三、表

  说表之前先介绍一个概念:抽象数据类型(Abstract Data Type),指的是带有一组操作的一些对象的组合。对于集合ADT,可以由添加、删除、查询等操作。表、栈、队列这三种数据结构就是最基本的ADT例子。

  数据结构与算法学习之路(java语言)一_第1张图片

  处理形如上图A0到An-1的一般表,我们定义A0是A1的前驱,A2是A1的后继,A0将没有前驱,An-1也没有后继。

  我么需要对表进行操作比如插入,删除那么我们把表当成一个单纯的数组进行操作就不是一个太好的选择,因此我们会处理另一种数据结构:链表

  数据结构与算法学习之路(java语言)一_第2张图片

  为了避免插入和删除的线性开销,我们需要保证表可以不连续存储,否则一旦更改表的元素,表的的某个整体都需要移动。链表由一系列节点组成,这些节点不必在内存中相连,每一个节点均包含有表元素和到包含元素的后继元节点的链(next链)。最后一个节点的next链指向null。

  remove方法可以通过一修改一个next引用来实现,insert方法需要使用new操作符从系统取得一个新节点,此后执行两次引用调整。数据结构与算法学习之路(java语言)一_第3张图片

  在这种链表结构中我们想要查找某个节点的数值需要遍历链表,因为节点的信息中并不会保存其前驱的任何信息,若我们想要删除最后一个节点则需要花费最长的查找时间,所以我们的做法是让每一个节点持有一个指向它在表中的前驱节点的链,作为双链表。

  数据结构与算法学习之路(java语言)一_第4张图片

你可能感兴趣的:(数据结构与算法学习之路(java语言)一)