数据结构算法以及算法分析
1.什么是算法?
其实在学C、C++、Java的过程中你已经接触了它,但是你可能从来没有听说过它,它就是你在写程序之前,脑子中构思的东西。
算法(Algorithm):是解决问题的方法和步骤。是对某一特定问题求解步骤的描述,它是指令的有限序列。
例如,在数组上实现选择排序的算法
思路:用嵌套双循环实现,
①外循环for(i=1;i
2.算法有以下几个特性:
⑴ 输入(Input):算法有0个或多个输入
⑵ 输出(Output):算法至少有1个或多个输出
⑶ 明确性(Definiteness):算法的每一步都有确定的含义,不存在二义性
⑷ 有限性(Finiteness):算法在有限的步骤之后会自动停止运行而不会无限循环运行,并且每个步骤都可以在可接受的时间内完成
⑸ 可行性(Effectiveness):算法的每一步都是可行的,也就是说每一步都能够执行有限的次数完成
3.算法设计的要求(好的算法应达到以下目标)
⑴ 正确性(Correctness):算法的正确性是指算法至少应该具有输入、输出和加工处理无歧异性、能正确反映问题的需求、能够得到问题的正确答案。
正确性分以下四个层次:
1)算法程序没有语法错误
2)算法程序对于合法的输入数据能够产生满足要求的输出结果。
3)算法程序对于非法的输入数据能够得出满足规格说明的结果。
4)算法程序对于精心选择的,甚至刁难的测试数据都有满足要求的输出结果
⑵ 可读性(Readability):算法设计的另一目的是为了便于阅读、理解和交流。
⑶ 健壮性(Robustness):当输入数据不合法时,算法也能做出相关处理,而不是产生异常或莫名其妙的结果。
⑷ 高效率低存储量:执行时间短的算法效率高,存储量需求是指算法在执行过程中需要的最大存储空间。
效率:对于同一个问题,如果有多个算法可以解决,执行时间短的算法效率高,执行时间长的效率低。
存储量:存储量需求指的是算法在执行的过程中需要的最大存储空间,主要指算法程序运行时所占用的内存或外部硬盘存储空间。
好的算法,当然应该四者兼备。
4.算法描述
算法有不同的语言描述实现版本,如C语言,Python语言,C++语言等。
这里采用类C语言代码来表示算法,它是标准C语言的扩充。
⑴ 预定义常量: MAXSIZE 、SUCCESS 、 TRUE、 FALSE、 ERROR
#define MAXSIZE 1000
#define TRUE 1
#define FALSE 0
#define ERROR 0
⑵ 类型定义说明:
typedef 定义具体数据结构类型。
例如:定义一个结构体类型student
typedef struct {
char name[20];
int data[3];
float average;
}student;
⑶ 算法描述-------函数形式描述;
[数据类型] 函数名([形式参数及说明])
{ 内部数据说明;
执行语句组;
}
3 赋值语句:
简单赋值:
变量名1=表达式;
成组赋值:
(变量名1,…,变量名n)=(表达式1,…,表达式n);
结构名1=结构名2;
变量名[ ]=表达式;
变量名[下标1..下标2]=变量名[下标3..下标4];
结构名={表达式1,表达式2,… 表达式n};
变量名[n]={值1,值2,…,值k};
串联赋值:
变量名1=变量名2=…=表达式;
⑸ 分支语句
1. if(条件表达式) 语句;
2. if(条件表达式) 语句1; else 语句2;
3. swith(表达式)
{ case 值1:语句1;break;
case 值2:语句2;break;
……
case 值n:语句n;break;
[default:语句n+1; ]
}
要善用switch结构,来简化多重条件和嵌套条件,使多分支结构清晰。
方括号括起来的部分如“[default:语句n+1;]”为可选项。
⑹ 循环语句
① for(赋值表达式;条件表达式;修改表达式)循环体语句;
② while(条件表达式)语句;
③ do 语句; while(条件表达式);【do while】
⑺ 结束语句
① return<表达式>;或return;用于函数结束。
② break语句:可用于循环语句中循环过程结束或跳出情况;switch语句中结束或跳出情况语句
③ continue语句:可用在循环语句中结束本次循环过程,进入下一次循环过程
④ exit语句:表示出现异常情况时,控制退出函数。
5.算法分析
⑴ 算法的时间复杂度
算法在机器上执行的时间,通常是从算法中选取一种对于研究的问题来说是基本运算的原操作,以该基本操作要 执行的次数,或称为语句的频度作为算法的时间量度。
记作: T(n)=O(f(n))。它表示随问题规模 n的增大算法执行时间的增长率和 f(n)的增长率相同,称作算法的渐进时间复杂度,简称为时间复杂度。其中 f(n)是问题规模 n的某个函数。
计算方法:
1.用常数1取代函数中所有的常数
2.只保留最高项
3.最好情况时间复杂度:代码在最坏情况下执行的时间复杂度。
常用的时间复杂度所耗费的时间从小到大依次是
O(1) < O(log n) < O(n) < O(nlog n) < O(n2) < O(n3) < O(n!) < O(nn)
一般法则
法则 1-----for循环
一次for循环的运行时间至多是该for循环内语句的运行时间X循环的次数。
for(i = 1 ; i <= n ; i++)
{
x = x + 1; /* 时间复杂度为O(n) */
}
法则 2-----嵌套的for循环
从里向外分析,在一组嵌套循环内部的一跳语句总的运行时间为该语句的运行时间X该组所有for循环的大小的乘积。
for( i = 0; i < n; i++)
{
for(j = 0; j < n; j++)
k++; /* 时间复杂度为O(n*n) */
}
法则 3-----顺序语句
将各个语句的运行时间求和即可,其中的最大值即为运行时间。
for(i = 1 ; i <= n ; i++)
{
x = x + 1; /* 时间复杂度为O(n) */
}
for( i = 0; i < n; i++)
{
for(j = 0; j < n; j++)
k++; /* 时间复杂度为O(n*n) */
}
/* 总时间复杂度为O(n*n) */
法则 4-----while语句
int count = 1;
while(count < n){
count *= 2;
/*时间复杂度为 O(1) 的程序步骤序列*/
}
/* 2^x = n 时间复杂度为O(log n) */
(2)空间复杂度
一个程序执行时,除了需要寄存本身所用的指令、常数、变量和输入数据以外,还需要辅助存储空间的多少 。
算法的空间复杂度是通过计算算法所需的存储空间实现
算法空间复杂度的计算公式记作: S(n)=O(f(n))S(n)=O(f(n)) S(n) = O(f(n))S(n)=O(f(n)) 。其中,n 为问题的规模, f(n)f(n) f(n)f(n) 为语句关于 n 所占存储空间的函数。
(3)递归:
int F(int x)
{
if(x == 0)
retuen 0;
else
return 2 * F(x-1) + X * X;
}
1.它是否就是循环逻辑?
答案是:虽然函数会用到这个函数本身,但是我们并没有用函数本身来定义函数的一个特定的实例。即使用F(5)来得到F(5)的值才是循环,通过F(4)来得到F(5)的值不是循环的。
2.实现递归的基本准则:
基准情形:递归中必须要有某些基准情形,他们不用递归就能求解。
不断推进:对于那些需要递归求解的情形,递归调用必须总能朝着产生基准情形的方向推进。
设计法则:假设所有的递归调用都能运行。
合成效益法则:在求解一个问题的同一实例时,切勿在不同的递归调用中做重复性的工作。
作者在算法和算法分析中借鉴了CSDN中的一位博主,下面附上原链接:https://blog.csdn.net/weixin_44988083/article/details/97542282