本文参考《数据结构(中国大学MOOC)》 from 浙江大学
一、定义
算法(Algorithm)是:
- 一个有限指令集;
- 可接收一些输入(输入可以是一个、多个,有些情况下也不需要输入);
- 产生输出(一定会有至少一个输出)
- 一定在有限步骤之后终止;
- 每一条指令必须:(1)有充分明确的目标,不可以有歧义;(2)在计算机能处理的范围之内;(3)描述应抽象,即不依赖于任何一种计算机语言以及具体的实现手段 。
?选择排序算法的伪码描述
这段伪码描述的最大特点就是——抽象。(我们不知道List到底是数组还是链表?Swap是用函数实现还是用宏实现?)
void Selection( int List[],int N)
{/* 将N个整数List[0]...List[N-1]进行非递减排序 */
for(i=0;i<N;i++){
MinPosition=ScanForMin(List,i,N-1);
/* 从List[i]到List[N-1]中找到最小元,并将其位置赋给MinPosition */
Swap(List[i],List[MinPosition]);
/* 将未排序部分的最小元换到有序部分的最后位置 */
}
}
二、什么是好的算法?
1.参考指标
空间复杂度S(n):根据算法写成的程序在执行时占用存储单元的长度。这个长度往往与输入数据的规模有关。
空间复杂度过高的算法可能导致使用的内存超限,造成程序非正常中断。
时间复杂度T(n):根据算法写成的程序在执行时耗费时间的长度。这个长度往往也与输入数据的规模有关。
时间复杂度过高的低效算法可能导致我们在有生之年等不到运行结果。
2.什么是好的算法?
在分析一般算法的效率时,我们经常关注两种复杂度:
- 最坏情况复杂度
- 平均复杂度
两者的关系为: 。通常,计算平均复杂度比较困难,所以我们最常使用的是最坏复杂度。
3.复杂度的渐进表示法
几点说明:
- 对于充分大的n而言,
表示的是
的上界;
表示的是
的下界
- 分析算法时,我们没有必要精确地知道算法要得到一个输出会运行多少步,我们只需要知道,随着输入数据规模的增大,该算法复杂度增长的趋势即可;
- 上界和下界的表示并不是唯一的,但我们在分析算法时,都希望得到的上界和下界尽可能地贴近实际情形,所以在写
时,我们选择的是能力范围内能找到的最小的上界;写
时,我们选择能力范围内能找到的最大的下界。
常用复杂度分析:
附:“二分法”的定义及伪码描述,并分析最坏、最好情况下的时间、空间复杂度。
1️⃣查找算法中的“二分法”的定义
给定N个从小到大排好序的整数序列List[],以及某待查找整数X;目标是找到X在List中的下标。
即,若有List[i]=X,则返回i;否则返回-1表示没有找到。
?“二分法”解决这一问题的思路是:
- 先找到序列的中点List[M],与X进行比较,若相等则返回中点下标;
- 否则,若List[M]>X,则在左边的子系列中查找;若List[M]<X,则在右边的子系列中查找
2️⃣伪码描述
int BinarySearch(int List[], int X,int length)
{
left=0;
right=length-1;
while(left<=right)
{
mid=(left+right)/2;
midvalue=List[mid];
if(X>midvalue) {left=mid+1;}
if(X<midvalue) {right=mid-1;}
if(X==midvalue) {return mid;}
}
return -1;
}
3️⃣复杂度分析
最好情况下,mid==X,此时时间复杂度为;最坏情况下,时间复杂度为
空间复杂度:需要根据list[]的数据类型判断,但这个函数中不存在函数递归调用,所以空间复杂度是固定的。
4️⃣C语言实现二分法
#include <stdio.h>
int binarySearch(int list[],int length,int s);
int main()
{
int x; //数组的值
int length; //数组长度
int cnt=0; //辅助变量
int s; //要查找的值
printf("请输出要查找的序列的长度:");
scanf("%d",&length);
if(length>0)
{
int a[length];
int i;
for(i=0;i<length;i++) //初始化数组
{
a[i]=0;
}
printf("请输入要查找的序列:\n");
scanf("%d",&x);
while(x!=-1)
{
a[cnt]=x;
cnt++;
scanf("%d",&x);
}
printf("请输入要查找的数字:\n");
scanf("%d",&s);
int j=binarySearch(a,length, s);
if(j!=-1)
{
printf("a[%d]=%d\n",j,s);
}
else
{
printf("Do not find.\n");
}
}
return 0;
}
//二分法
int binarySearch(int list[],int length,int s)
{
int mid,midvalue;
int left=0,right=length-1;
while(left<=right)
{
mid=(left+right)/2;
midvalue=list[mid];
if(s>midvalue)
{
left=mid+1;
}
else if(s<midvalue)
{
right=mid-1;
}
else
{
return mid;
}
}
return -1;
}