java数据结构基础:算法

目录
  • 数据结构和算法关系
    • 高斯求和
    • 算法定义
    • 算法的特性
    • 算法设计的要求
    • 算法效率的度量方法
    • 函数的渐进增长
  • 总结

数据结构和算法关系

虽然这个标题起的叫数据结构,但是我却总结算法。。。我不是没事找抽,只是呢,在学数据结构的时候,算法是你肯定离不开的东西。

你平时在网上看到的那些文章,在你不经意间搜的时候,是不是都是搜的数据结构与算法这七个字。这说明啥,这说明他们俩是离不开的。

给你打个比方,你想看德云社相声(我也想看),有一天你最想看小岳岳专场,想看小白专场。但是呢,走到园子里之后发现,他们今天生病了,换成了另一批人,你开心吗,不开心对不对。

所以,数据结构和算法也是这样的。没有其中的任何一个都不行。

但是,根据大学里边的概念性的东西来说,类似于我们学校,算法是单独开设课程,并不是和数据结构一起。所以,这一章还是理论。

高斯求和

想必看到这儿的人肯定对这个人早有耳闻。
如果让你来做累加求和,你肯定会写这样的代码:

int sum=0;
int n=100;
for(int i=0;i<=n;i++){
sum+=i;
}

这样做确实没错,但是问题来了,你这和循环了多少次?如果没写错的话,是101次吧。为什么呢,因为你在每次累加的时候都会去走一遍for循环,这样就会平平增加不必要的时间去运算,你有这时间,你根本就抢不到亚索。

我们直接来看这个天才当时是怎么做的。

因为sum=1+2+3+…+100。

但是呢,sum=100+99+98+…+1

如果把他们两个加起来,那就是2sum=101+101+101+…+101

一共多少个101,100个吧,那如果去除2呢,结果不就是5050了。用代码怎么写?

int i=0;
int sum=0
int n=100;
sum=(1+n)*n/2

这就是神童,这就是大佬,思考问题的方面都和我们不一样。

也就是说,用这种方式,我们省略掉了那100次多余的运算,只需要一次运算就能得出答案。

如果让你加到一亿呢?你想想哪种效率会更高。

算法定义

算法这个词最早是提出在公元825年的一个叫阿勒·花剌子的一个波斯数学家写的《印度数字算术》里面。

目前来说,普遍的定义就是:

算法是解决特定问题求解步骤的描述,在计算机中表现为指令的有限序列,并且每条指令表示一个或者多个操作

刚才的问题我们也看了,对于一个问题可以有多个方法解除答案。那么问题来了,有木有通用的算法?
这个答案其实就和你去医院买药一样,请问有没有能治所有病的药答案一样。

算法的特性

算法具有五个特性:输入、输出、有限、确定、可行

输入输出

这个比较好理解。算法具有零个或者多个输入。

有穷性

指的是算法在执行有限的步骤之后,自动结束而不会出现无限循环,并且每一个步骤在可接受的时间内完成。
当然,这里的有穷指的是在实际意义中合理的。

可行性

算法的每一步都是必须可行的,也就是说,每一步都能通过执行有限次数完成。

算法设计的要求

刚才我们说过,算法并不是唯一的。那我们在处理一个问题的时候,就必须要事先设计好算法才去解决问题。

正确性

算法的正确性是指算法至少应该具有输入和输出和加工厂处理无歧义性、能正确反映问题的需求、能狗得到问题得正确答案。

可读性

算法设计的另一目的就是为了方便阅读,理解和交流

你说你写一个很牛逼的代码,别人看不懂,,,怎么去承认你牛逼呢是不是

健壮性

当输入数据不合法时,算法也能做出相应的处理,而不是产生异常或者莫名奇妙的结果

时间效率高和存储量低

算法设计应该尽量满足时间效率高和存储量低的特点

这一点我迟迟没有达到。。。。

算法效率的度量方法

算法的效率指的就是算法的执行时间。那我们怎么去算一个他的执行时间呢?

最简单的方法其实就是用计算机的计时功能来计算不同算法的效率是高是低。

事后统计法

通过设计好的测试程序和数据,利用计算机计时器对不同算法编制的程序的运行时间进行比较,从而确定算法效率的高低

但是这种方法有很大的缺陷。

事前分析估算方法

在计算机程序编制前,依据统计方法对算法进行估算

经过分析发现,一个用高级程序语言编写的程序在计算机上运行时所消耗的时间取决于这些:

  1. 算法采用的策略、方法
  2. 编译产生的代码质量
  3. 问题的输入规模
  4. 机器执行指令的速度

其实你想想,这上面四条哪一条最重要?无非就是问题的输入规模。

所谓的输入规模就是输入量的大小;

我们再分析一下刚才的高斯求和;

第一种:

int sum=0; // 执行了1次
int n=100; // 执行了一次
for(int i=0;i<=n;i++){ // 执行了n+1次
sum+=i; // 执行了n次
}

第二种:

int sum=0; // 执行了一次
int n=100; // 执行了1次
sum=(1+n)*n/2; // 执行了1次

孰优孰劣,这下看得出来吧;

我们再看一个衍生算法:

int i;
int j;
int x=0;
int sum=0;
int n=100;
for(i=1;i<=n;i++){
	for(j=1;j<=n;j++){
		x++;
		sum+=x;
	}
}

这个例子很好理解,其实也就是多循环了一百次而已,那么最后算出的次数是多少呢?n²,没错吧

我们不关心程序用的什么语言,在什么机器上执行,只关心算法。最终在分析程序的运行时间时,最重要的是把程序堪称是独立于程序设计的算法或一系列步骤。

可以从问题中得到启示,同样的规模,都是输入n,求和算法的不同,使得这个运行效率也是不同;

第一种总结出来就是f(n)=n;

第二种简单了,就是f(n)=1;第三种呢?f(n)=n²

用一张图展示一下?(来源于网络)

函数的渐进增长

我们现在来举个例子,两个算法a和b哪个更好。假设两个算法的输入规模都是n,算法a要做2n+3次操作(两次n循环,3次运算),算法b做3n+1次操作。

用一张表来演示一下:

次数 算法a(2n+3) 算法a'(2n) 算法b(3n+1) 算法b'(3n)
n=1 5 2 4 3
n=2 7 4 7 6
n=3 9 6 10 9
n=10 23 20 31 30
n=100 203 200 301 300

看这张表,最后我们总结出算法a总体来说优于算法b

输入规模n在没有限制的情况下,只要超过一个数n,这个函数就总是大于另一个函数,我们称为是渐进增长

函数的渐进增长:给定两个函数f(n)和g(n),如果存在一个整数N使得队医所有的n>N,f(n)总是比g(n)大,那么我们说f(n)的渐进增长快于g(n)

从中我们发现,随着n的增大,后面的+3还是+1其实不怎么影响最终的结果,所以我们可以去忽略这些常数。我们再看看第二个例子:

次数 算法c(4n+8) 算法c'(n) 算法d(2n²+1) 算法d'(n²)
n=1 12 1 3 1
n=2 16 2 9 4
n=3 20 3 19 9
n=10 48 10 201 100
n=100 408 100 20 001 10 000

当n<=3的时候,算法c要差于算法d,但是当n>3之后,优势就开始出来了。

所以最后总结出,与最高次项的常数并不重要。

其实根据这两个表,大致都能分析出来,某个算法,随着n的增大,他会越来越优于另一种算法,或者越来越差于另一种算法

这其实就是事前估算方法的理论依据,通过算法时间复杂度来估算时间效率

算法时间复杂度

定义:在进行算法分析时,语句的执行次数T(n)是关于问题规模n的函数,进而分析T(n)随n的变化情况而确定T(n)的数量级。算法的时间复杂度,也就是算法的时间量度,记作:T(n)=O(f(n))。他表示随着问题规模n的增大,算法执行时间的增长率和f(n)的增长率相同,称作算法的渐进时间复杂度,简称为时间复杂度。其中f(n)是问题规模n的某个函数;

总结

本篇文章就到这里了,希望能给你带来帮助,也希望您能够多多关注我们的更多内容!

(0)

相关推荐

  • java数据结构基础:栈

    目录 准备工作 编码环节 push方法 pop方法 empty方法 全部代码 总结 准备工作 工具:idea+jdk8 技术要求:java基础语法 编码环节 首先,我们得先确定下来,用什么数据来模拟栈的操作.由于是一个一个的元素放入栈里面,我们可以考虑用数组来实现. 以上是Java官方文档中的栈定义,我们也只需要实现三个方法:判断是否为空.移除栈顶对象.添加元素到栈的尾部 所以我们事先得定义一个数组: Objects[] arr; 数组定义好了之后呢,想想,我们怎么去获取到栈尾部或者栈首的元素呢

  • java数据结构基础:单,双向链表

    目录 单向链表 单链表图解 代码 双向链表 编码 总结 单向链表 单向链表比顺序结构的线性表最大的好处就是不用保证存放的位置,它只需要用指针去指向下一个元素就能搞定. 单链表图解 图画的比较粗糙,简单的讲解一下: 上面四个长方形,每个长方形都是一个节点.在长方形中,一种包含两个东西,一个是当前节点的元素,一个是指向下一节点的地址.这个下一个节点的地址指向了下一个节点中的元素.以此类推. 在最左边的叫做头节点,同样,最后面的叫尾节点. 所以,我们所有的操作都是根据节点来进行操作. 代码 这些代码都

  • java数据结构基础:线性表

    目录 前言 需求分析 编码 add方法 getIndex方法 pop方法 insert方法 getAll 全部代码 总结 前言 其实线性表在生活中和栈的结构差不多.昨天总结了一篇单链表,也是线性表的一种. 今天用另一种写法来控制指针的移动实现数据的顺序存储结构. 需求分析 首先要明确,这种顺序存储结构的线性表底层用什么.根据之前查看过的源码来看,list一般都是以数组为底层.我们也不例外. 其次,我们还得去定义好线性表的长度,以及每个元素的指针. private Object[] arr; //

  • Java常见基础数据结构

    目录 栈: 队列: 数组: 链表: 红黑树: 总结 栈: stack,又称堆栈,他是运算受限的线性表,其限制是仅允许在表的一端进行插入和删除操作,不允许在其他任何位置进行添加.查找.删除等操作. 简单的来说,采用该结构的集合,对元素的存取有如下几个特点 1.先进后出. 2.栈的入口.出口都是栈的顶端位置. 压栈:就是存元素,把元素存储到栈的顶端位置,栈中已有元素一次向栈底方向移动一个位置. 弹栈:就是取元素,把栈顶端的元素取出,栈中已有元素依次向栈顶方向移动一个位置. 队列: queue,简称队

  • java数据结构基础:绪论

    目录 基本概念和术语 数据 数据元素 数据项 数据对象 结构 数据结构 逻辑结构与物理结构 逻辑结构 物理结构 抽象数据类型 总结 基本概念和术语 要想知道数据结构是什么,我们首先得去知道,数据和结构是什么: 数据结构=数据+结构 也就是说,我们先去研究数据,再去把这些数据组成一定得样子(结构),自然而然的成了数据结构 数据 数据:是描述客观事物的符号,是计算机中可以操作的对象,是能被计算机识别并输入给计算机处理的符号集合 这样说可能还是有人觉得头痛,说直白点,空气粒子组成了空气,一个个的人组成

  • java数据结构基础:算法

    目录 数据结构和算法关系 高斯求和 算法定义 算法的特性 算法设计的要求 算法效率的度量方法 函数的渐进增长 总结 数据结构和算法关系 虽然这个标题起的叫数据结构,但是我却总结算法...我不是没事找抽,只是呢,在学数据结构的时候,算法是你肯定离不开的东西. 你平时在网上看到的那些文章,在你不经意间搜的时候,是不是都是搜的数据结构与算法这七个字.这说明啥,这说明他们俩是离不开的. 给你打个比方,你想看德云社相声(我也想看),有一天你最想看小岳岳专场,想看小白专场.但是呢,走到园子里之后发现,他们今

  • Java数据结构与算法之栈(Stack)实现详解

    本篇是java数据结构与算法的第2篇,从本篇开始我们将来了解栈的设计与实现,以下是本篇的相关知识点: 栈的抽象数据类型顺序栈的设计与实现链式栈的设计与实现栈的应用 栈的抽象数据类型   栈是一种用于存储数据的简单数据结构,有点类似链表或者顺序表(统称线性表),栈与线性表的最大区别是数据的存取的操作,我们可以这样认为栈(Stack)是一种特殊的线性表,其插入和删除操作只允许在线性表的一端进行,一般而言,把允许操作的一端称为栈顶(Top),不可操作的一端称为栈底(Bottom),同时把插入元素的操作

  • java数据结构排序算法之归并排序详解

    本文实例讲述了java数据结构排序算法之归并排序.分享给大家供大家参考,具体如下: 在前面说的那几种排序都是将一组记录按关键字大小排成一个有序的序列,而归并排序的思想是:基于合并,将两个或两个以上有序表合并成一个新的有序表 归并排序算法:假设初始序列含有n个记录,首先将这n个记录看成n个有序的子序列,每个子序列长度为1,然后两两归并,得到n/2个长度为2(n为奇数的时候,最后一个序列的长度为1)的有序子序列.在此基础上,再对长度为2的有序子序列进行亮亮归并,得到若干个长度为4的有序子序列.如此重

  • java数据结构与算法之双向循环队列的数组实现方法

    本文实例讲述了java数据结构与算法之双向循环队列的数组实现方法.分享给大家供大家参考,具体如下: 需要说明的是此算法我并没有测试过,这里给出的相当于伪代码的算法思想,所以只能用来作为参考! package source; public class Deque { private int maxSize; private int left; private int right; private int nItems; private long[] myDeque; //constructor p

  • java数据结构与算法之快速排序详解

    本文实例讲述了java数据结构与算法之快速排序.分享给大家供大家参考,具体如下: 交换类排序的另一个方法,即快速排序. 快速排序:改变了冒泡排序中一次交换仅能消除一个逆序的局限性,是冒泡排序的一种改进:实现了一次交换可消除多个逆序.通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列. 步骤: 1.从数列中挑出一个元素,称为 "基准"(piv

  • java数据结构排序算法之树形选择排序详解

    本文实例讲述了java数据结构排序算法之树形选择排序.分享给大家供大家参考,具体如下: 这里我们就来说说选择类排序之一的排序:树形选择排序 在简单选择排序中,每次的比较都没有用到上次比较的结果,所以比较操作的时间复杂度是O(N^2),想要降低比较的次数,则需要把比较过程中的大小关系保存下来.树形选择排序是对简单选择排序的改进. 树形选择排序:又称锦标赛排序(Tournament Sort),是一种按照锦标赛的思想进行选择排序的方法.首先对n个记录的关键字进行两两比较,然后在n/2个较小者之间再进

  • java数据结构与算法之插入排序详解

    本文实例讲述了java数据结构与算法之插入排序.分享给大家供大家参考,具体如下: 复习之余,就将数据结构中关于排序的这块知识点整理了一下,写下来是想与更多的人分享,最关键的是做一备份,为方便以后查阅. 排序 1.概念: 有n个记录的序列{R1,R2,.......,Rn}(此处注意:1,2,n 是下表序列,以下是相同的作用),其相应关键字的序列是{K1,K2,.........,Kn}.通过排序,要求找出当前下标序列1,2,......,n的一种排列p1,p2,........pn,使得相应关键

  • java数据结构与算法之冒泡排序详解

    本文实例讲述了java数据结构与算法之冒泡排序.分享给大家供大家参考,具体如下: 前面文章讲述的排序算法都是基于插入类的排序,这篇文章开始介绍交换类的排序算法,即:冒泡排序.快速排序(冒泡排序的改进). 交换类的算法:通过交换逆序元素进行排序的方法. 冒泡排序:反复扫描待排序记录序列,在扫描的过程中,顺次比较相邻的两个元素的大小,若逆序就交换位置. 算法实现代码如下: package exp_sort; public class BubbleSort { public static void b

  • Java数据结构与算法之栈(动力节点Java学院整理)

    stack,中文翻译为堆栈,其实指的是栈,heap,堆.这里讲的是数据结构的栈,不是内存分配里面的堆和栈. 栈是先进后出的数据的结构,好比你碟子一个一个堆起来,最后放的那个是堆在最上面的. 队列就是排队买苹果,先去的那个可以先买. 栈 public class Stack { private int array[]; private int max; private int top; public Stack(int max){ this.max = max; array = new int[m

  • java数据结构与算法之希尔排序详解

    本文实例讲述了java数据结构与算法之希尔排序.分享给大家供大家参考,具体如下: 这里要介绍的是希尔排序(缩小增量排序法). 希尔排序:通过比较相距一定间隔的元素来工作:各趟比较所用的距离(增量)随着算法的进行而减小,直到只比较相邻元素的最后一趟排序为止.是插入排序的一种,是针对直接插入排序算法的改进. 算法思想:先将要排序的序列按某个增量d分成若干个子序列,对每个子序列中全部元素分别进行直接插入排序,然后再用一个较小的增量对它进行分组,在每组中再进行排序.当增量减到1时,整个要排序的数被分成一

随机推荐