数据结构与算法学习笔记(一)

   本篇主要内容为数据结构与算法的入门和基本概念的了解
    

  自学Java有了一段时间了,也参加了几个公司的笔试,结果发现,对于校招的同学来说,笔试中对于数据结构与算法的考察还是比较多的,这一系列的博客是对最近学习的数据结构与算法的记录,算是一个小小的读书笔记吧。


       数据结构是计算机中存储、组织数据的方式。精心选择的数据结构可以带来最优效率的算法。

学习之前先来看几个例子:

   1、 思考一个问题,如果你是一个图书馆管理员,你要怎么摆放图书才能够更高效的摆放或者查找到你算需要的那一本图书呢?

    方法一:随便摆放 ,任何时候有新书进来,哪里有空放在哪里 ----------插入效率高,查找时效率低。

    方法二 :按照书名首字母拼音顺序摆放     ----------查找效率高,新书插入效率极低。

    方法三:把书架划分成几个区域,每个区域指定摆放某种特定的图书,每个区域内按书名首字母顺序摆放----种类少时,插入效率低;种类多时,查找效率低,可能造成空间浪费。

    2、实现一个函数PrintN(int n) 使得该函数打印出从1开始到n的所有正整数。

    

public void forNum(int num){
		for(int i=1;i<num;i++){
			System.out.println(i);
		}
	}
	
public  void recuNum(int num){
		if(num>0){
			recuNum(num-1);
			System.out.println(num);
		}
		return;
	}


分别用for循环与递归来实现,测试发现,当测试用例n数值超过10万时,递归方法会出现内存溢出的错误。

Exception in thread "main" java.lang.StackOverflowError
	at com.hongxin.Test75.TestForAndRecursion.recuNum(TestForAndRecursion.java:15)
	at com.hongxin.Test75.TestForAndRecursion.recuNum(TestForAndRecursion.java:15)
	at com.hongxin.Test75.TestForAndRecursion.recuNum(TestForAndRecursion.java:15)
	at com.hongxin.Test75.TestForAndRecursion.recuNum(TestForAndRecursion.java:15)
	at com.hongxin.Test75.TestForAndRecursion.recuNum(TestForAndRecursion.java:15)
	at com.hongxin.Test75.TestForAndRecursion.recuNum(TestForAndRecursion.java:15)
	at com.hongxin.Test75.TestForAndRecursion.recuNum(TestForAndRecursion.java:15)
	at com.hongxin.Test75.TestForAndRecursion.recuNum(TestForAndRecursion.java:15)
	at com.hongxin.Test75.TestForAndRecursion.recuNum(TestForAndRecursion.java:15)
	at com.hongxin.Test75.TestForAndRecursion.recuNum(TestForAndRecursion.java:15)
	at com.hongxin.Test75.TestForAndRecursion.recuNum(TestForAndRecursion.java:15)
	at com.hongxin.Test75.TestForAndRecursion.recuNum(TestForAndRecursion.java:15)
	at com.hongxin.Test75.TestForAndRecursion.recuNum(TestForAndRecursion.java:15)
	at com.hongxin.Test75.TestForAndRecursion.recuNum(TestForAndRecursion.java:15)
	at com.hongxin.Test75.TestForAndRecursion.recuNum(TestForAndRecursion.java:15)
	at com.hongxin.Test75.TestForAndRecursion.recuNum(TestForAndRecursion.java:15)
	at com.hongxin.Test75.TestForAndRecursion.recuNum(TestForAndRecursion.java:15)
	at com.hongxin.Test75.TestForAndRecursion.recuNum(TestForAndRecursion.java:15)
	at com.hongxin.Test75.TestForAndRecursion.recuNum(TestForAndRecursion.java:15)
	at com.hongxin.Test75.TestForAndRecursion.recuNum(TestForAndRecursion.java:15)
	at com.hongxin.Test75.TestForAndRecursion.recuNum(TestForAndRecursion.java:15)
	at com.hongxin.Test75.TestForAndRecursion.recuNum(TestForAndRecursion.java:15)
	at com.hongxin.Test75.TestForAndRecursion.recuNum(TestForAndRecursion.java:15)
	at com.hongxin.Test75.TestForAndRecursion.recuNum(TestForAndRecursion.java:15)
	at com.hongxin.Test75.TestForAndRecursion.recuNum(TestForAndRecursion.java:15)
	at com.hongxin.Test75.TestForAndRecursion.recuNum(TestForAndRecursion.java:15)

    3、多项式的标准表达式可以写为: f(x) = a0 + a1x + a2x2 +…+ anxn 现给定一个多项式的阶数 n,并将全体系数存放在数组 a[ ]里。请写程序计算这个多项式在给定点 x 处的值。

public double func1(int n,double[] a,double x){
    // n为阶数  a为多项式的 系数数组,x为给定点
		
    double sum = a[0];
		
    for(int i =1;i<=n;i++){
	sum+=a[i]*Math.pow(x,i);
	}
		
	return sum;
}
 
 
	  /**
	 * 秦九韶法
            f(x) = a0 + x (a1+ x (a2 +… + x (an) …)
			double f( int n, double a[], double x )
	 * @param n
	 * @param a
	 * @param x
	 * @return
	 */
	public double func2(int n,double[] a,double x){
		double sum = a[n];
		for (int i=n; i>0; i--)
			sum = a[i-1] + x*sum;
		return x;
	}

   通过测试,秦九韶法的用时比直接暴力算法快了一个数量级。


    从上面的三个例子可以看出:

    即使解决一个非常简单的问题,往往也有多种方法,且不同方法之间的效率可能相差甚远 

     解决问题方法的效率 跟数据的组织方式有关(如例1)

     跟空间的利用效率有关(如例2)

     跟算法的巧妙程度有关(如例3)


下面介绍一些术语:

    数据对象: 计算机要处理的事物,如例1中“图书” 。

    操作:处理事物的动作集合,如例1中的“查找”和“插入”,例2的函数“求值”等。   

    算法: 操作的实现方法,如例1.1的按字母序排放的“查找”和“插入”、例1.2的“直接法”和例1.3的“秦九韶法”等。 通常一个算法用一个函数来实现。

    逻辑结构:数据对象的逻辑组织关系。分为“线性”、“树”和“图”。例1中按方法1来处理,就是把图书集看成是线性的结构;按方法3来处理,就是把图书集看成是树形的结构。

    物理结构:数据对象信息在计算机内存中的存储组织关系。一般分为“顺序存储”和“链式存储”。

    数据类型: 数据对象的类型确定了其“操作集”和“数据定义域”。

    抽象数据类型: “抽象”的意思,是指我们描述数据类型的方法是不依赖于具体实现的,即数据对象集和操作集的描述与存放数据的机器无关、与数据存储的物理结构无关、与实现操作的算法和编程语言均无关。简而言之,抽象数据类型只描述数据对象集和相关操作集“是什么”,并不涉及“如何做到”的问题。

    算法是解决某一类问题的步骤的描述。一般而言,算法应该符合以下五项要求:
      (1) 输入:它接受一些输入(有些情况下不需要输入);
     (2) 输出:至少产生一个输出;
     (3) 确定性:算法的每一步必须有充分明确的含义,不可以有歧义;
     (4) 有限性:算法是一个有限指令集,并一定在有限步骤之后终止;
     (5) 可行性:算法的每一步必须在计算机能处理的范围之内。      
     另外,算法的描述可以不依赖于任何一种计算机语言以及具体的实现手段。可以用自然语言、流程图等方法来描述。

未完待续。
参考资料:浙江大学-数据结构课程-陈越





猜你喜欢

转载自blog.csdn.net/Zhang_hongxin/article/details/80929388