数据结构与算法(一)

第一章 什么是算法和数据结构

1.什么是算法

算法,对应的英文是algorithm,这是一个很古老的概念,最早来自于数学领域。在数学领域,算法是用于解决某一类问题的公式或思想。
而我们所说的算法是计算机领域的算法,它的本质是一系列的指令,用于解决特定的运算和逻辑问题。

算法有简单的和复杂的
简单的算法,如一列整数找出最大值。
在这里插入图片描述

复杂的算法,如在多种物品里选择装入背包的物品,使背包里的总价值最大 ,或者找出一个城市到另一个城市的最短距离。
在这里插入图片描述
算法有高效的,也有拙劣的
在计算机领域衡量算法好坏的重要标准是:空间复杂度(运行时间的长短)时间复杂度(占用空间的大小)

1.1时间复杂度
1.1.1 基本操作次数

为了方便计算,我们对程序基本操作执行次数的统计,设T(n)为程序基本操作次数的函数(也可以认为是相对执行时间),n为输入规模。

  • 场景一 T ( n ) = 3 n T(n) = 3n T(n)=3n,执行次数是线性
void eat1(int n){
 	for(int i=0; i<n; i++){
 		System.out.println("等待1分钟"); 
   		System.out.println("等待1分钟"); 
   		System.out.println("吃1cm 面包");
	}
}
  • 场景二 T ( n ) = 3 l o g n T(n) = 3logn T(n)=3logn,执行次数是用对数计算的。
void eat2(int n){
 	for(int i=n; i >1; i/=2){
 		System.out.println("等待1分钟"); 
   		System.out.println("等待1分钟"); 
   		System.out.println("吃1cm 面包");
	}
}
  • 场景三 T(n) = 3 执行次数是常量
void eat3(int n){
 	System.out.println("等待1分钟"); 
   	System.out.println("等待1分钟"); 
   	System.out.println("吃1cm 面包");
}
  • 场景四 T ( n ) = 0.5 n 2 + 0.5 n T(n) = 0.5n^2 + 0.5n T(n)=0.5n2+0.5n,执行次数是用多项式计算的。
void eat4(int n){
 	for(int i=0; i<n; i++){
 		for(int j = 0; j<i;j++){
 			System.out.println("等待1分钟");
 		}		 
   		System.out.println("吃1cm 面包");
	}
}
1.1.2 渐进时间复杂度

官方定义如下:
若存在函数f(n),使得当n趋近与无穷大时,T(n)/f(n)的极限值为不等于零的常数,则称f(n)是T(n)的同数量级函数。记作T(n) = O(f(n)),称为O(f(n)),O为算法的渐进时间复杂度,简称为时间复杂度。
因为渐进时间复杂度用大写O来表示,所有也被称为大O表示法。
如何推导出时间复杂度?如下有几个原则
- 如果运行时间是常数量级,则用常数1表示
- 只保留时间函数中的最高阶项
- 如果最高阶项存在,则省钱最高阶项前面的系数

  • 场景一 T ( n ) = 3 n , T(n) = 3n, T(n)=3n最高阶项为3,省去系数3,则转化的时间复杂度为: T ( n ) = O ( n ) T(n) = O(n) T(n)=O(n)
  • 场景二 T ( n ) = 3 l o g n , T(n) = 3logn, T(n)=3logn最高阶项为3,省去系数3,则转化的时间复杂度为: T ( n ) = O ( l o g n ) T(n) = O(logn) T(n)=O(logn)
  • 场景三 T ( n ) = 3 , T(n) = 3, T(n)=3最高阶项为3,省去系数3,则转化的时间复杂度为: T ( n ) = O ( 1 ) T(n) = O(1) T(n)=O(1)
  • 场景四 T ( n ) = 0.5 n 2 + 0.5 n , T(n) = 0.5n^2 + 0.5n, T(n)=0.5n2+0.5n最高阶项为 0.5 n 2 0.5n^2 0.5n2,省去系数0.5,则转化的时间复杂度为: T ( n ) = O ( n 2 ) T(n) = O(n^2) T(n)=O(n2)
    这四种时间复杂度当n的取值足够大时,可以得出如下结论: O ( 1 ) < O ( l o g n ) < O ( n ) < O ( n 2 ) O(1)<O(logn)<O(n)<O(n^2) O(1)<O(logn)<O(n)<O(n2)
1.2空间复杂度
1.2.1 什么是空间复杂度

在运行一段程序时,我们不仅需要执行各种运算指令,同时还会根据需要储存一些临时的中间数据,以便后续指令可以方便地继续执行。储存中间数据所需要的内存大小我们叫做——空间复杂度,同样用大O表示,记作 S ( n ) = O ( f ( n ) ) S(n) = O(f(n)) S(n)=O(f(n))

1.2.2 空间复杂度的计算
  1. 常量空间
    当算法空间大小固定,和输入规模没有直接关系时,空间复杂度记做 O ( 1 ) O(1) O(1)。如下代码
void fun1(int n) {
	int var = 3;
	...
}
  1. 线性空间
    当算法分配的空间是一个线性的集合(如数组),并且集合大小和输入规模n成正比时,空间复杂度记作 O ( n ) O(n) O(n)。如下代码
void fun2(int n) {
	int[] array = new int[n];
	...
}
  1. 二维空间
    当算法分配的空间是一个二维数组集合,并且集合的长度和宽度都与输入规格n成正比时,空间复杂度记作 O ( n 2 ) O(n^2) O(n2)。如下代码
void fun3(int n) {
	int[][] array = new int[n][n];
	...
}
  1. 递归空间
    递归是一个比较特殊的场景。虽然递归代码中并没有显式地声明变量或者集合,但是计算机在执行程序时,会专门分配一块内存用来储存”方法调用栈“。
    方法调用栈“包括进栈和出栈两个行为。
    当进入一个新方法时,执行入栈操作,把调用的方法和参数信息压入栈中。当方法返回时,执行出栈操作,把调用的方法和参数信息从栈中弹出。如下代码
void fun4(int n) {
	if(n<1) {
		return;
	}
	fun4(n-1);
	...
}

从”方法调用栈“的出入栈操作可以看出,其内存空间和递归深度成正比。纯粹的递归操作的空间复杂度也是线性的,所以空间复杂度是 O ( n ) O(n) O(n)

2.什么是数据结构

数据结构,对应的英文单词是data structure,是数据的组织、管理和储存格式,其使用的目的是为了高效地访问和修改数据。

数据结构主要有哪些组成方式?

  1. 线性结构
    线性结构是最简单的数据结构,包括数组、链表,以及由它们衍生出来的栈、队列、哈希表。


  2. 树是相对复杂的数据结构,其中比较有代表性的是二叉树,由它又衍生出了堆之类的数据结构。


  3. 图是更为复杂的数据结构,因为在图中会呈现出多对多的关联关系。

  4. 其他数据结构
    除以上的几种数据结构以外,还有一些其他的千奇百怪的数据结构。它们由基本数据结构变形而来,用于解决特定问题,如跳表、哈希链表、位图等。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值