如果是输出型参数,要加&,即使用引用传递
1.1 数据结构
-
定义
默认情况下,数据结构中讨论的数据都是数据对象。
-
数据:所有能够输入到计算机中,且能被计算机处理的符号的集合
-
数据元素:是数据(集合)中的一个“个体”,它是数据的基本单位
-
数据项:数据项是用来描述数据元素的,它是数据的最小单位
-
数据对象:具有相同性质的若干个数据元素的集合,如整数数据对象是所有整数的集合。
-
数据结构 = 数据对象 + 结构
(逻辑结构 存储结构 数据运算)
-
-
逻辑结构
从开始元素、终端元素、前驱元素、后继元素来区分
- 集合
- 线性结构
- 树形结构
- 图形结构
-
存储结构
- 顺序存储结构
- 链式存储结构
- 索引存储结构
- 哈希(散列)存储结构
-
数据类型
- 高等程序语言提高了数据类型
- 数据类型是一个值的集合和定义在此集合上的一组操作的总称
- 比如 C/C++中的整型 值 和 操作
-
抽象数据类型
ADT=数据的逻辑结构+数据运算(运算描述) (数据对象 数据关系 基本运算)
用编程实现该数据结构
-
数据结构求解问题过程
1.2 算法
-
算法的五个重要的特性
- 有穷性
- 确定性 无二义性
- 可行性
- 有输入
- 有输出
-
算法分析基础
- CPU时间 时间性能分析
- 内存空间 空间性能分析
-
算法时间复杂度分析
控制结构(顺序、分支和循环)原操作
-
算法分析方式:
- 事后分析统计算法 (语言不同 执行环境不通)
- 事前估算分析方式
-
分析算法的执行时间 原操作的执行次数(也称为频度)T(n)
#define MAX 20 //定义最大的方阶 void matrixadd(int n,intA[MAX][MAX], int B[MAX][MAX], int C[MAX][MAX]) { int i,j; for (i=0;i<n;i++) //① for (j=0;j<n;j++) //② C[i][j]=A[i][j]+B[i][j]; //③ }
1处 频度为n+1,循环体执行n次
2处频度为n(n+1)
3处频度为n^2
所有语句频度之和为 T(n)=n+1+n(n+1)+n2=2n2+2n+1
-
O(n)是T(n)的紧凑上界
例如,T(n)=2n2+2n+1=O(n2)
-
时间复杂度是指T(n)的最高数量级的比较
-
一般地、
- 一个没有循环的算法的执行时间与问题规模n无关,记作O(1),也称作常
数阶。 - 一个只有一重循环的算法的执行时间与问题规模n的增长呈线性增大关系, 记作O(n),也称线性阶。
- 其余常用的算法时间复杂度还有平方阶O(n2)、立方阶O(n3)、对数阶 O(log2n)、指数阶O(2^n)等。
- 一个没有循环的算法的执行时间与问题规模n无关,记作O(1),也称作常
-
各种不同算法时间复杂度的比较关系如下
- O(1)<O(log2n)<O(n)<O(nlog2n)<O(n2)<O(n3)<O(2^n)<O(n!)
- 多项式阶(P问题) 后两个指数阶(NP问题)
- NP问题是否转换为P问题 是难题
-
简化的算法时间复杂度分析
-
算法中的基本操作一般是最深层循环内的原操作。
-
算法执行时间大致 = 基本操作所需的时间 ×其运算次数。
-
在算法分析时,计算**T(n)**时仅仅考虑基本操作的运算次数。
-
例子: 分析算法时间复杂度
void func(int n) { int i=0,s=0; while(s<n) { i++; // 基本操作 s=s+i; //基本操作 } }
解:对于while循环语句,设执行的次数为m,变量i从0 开始递增1,直到m为止,有: 循环结束:s=m(m+1)/2≥n,或者m(m+1)/2+k=n 。则求得T(n)=m=O(根号n)
-
-
-
算法空间复杂度分析
空间复杂度:用于度量一个算法在运行过程中临时占用的储存空间大小(函数体内分配的空间)
-
其他情况的算法分析
-
最好、最坏、平均时间复杂度分析
-
递归算法的时空复杂度分析 (变长时空分析)
void fun(int a[],int n,int k) //数组a共有n个元素 { int i; if (k==n-1) for (i=0;i<n;i++) //n次 printf("%d\n",a[i]); else { for (i=k;i<n;i++) //n-k次 a[i]=a[i]+i*i; fun(a,n,k+1); } } // 求fun(a,n,0)的时间复杂度
T(n,k)=n k = n-1
T(n,k)=(n-k)+T(n,k+1) 其他情况
T(n)=T(n,0)=n+T(n,1)=n+(n-1)+T(n,2)=…
=n+(n-1)+(n-2)+…+2+n
=O(n^6)
// 求fun(a,n,0)空间复杂度
设fun(a,n,0)的空间为S(n),fun(a,n,k)的空间为S1(n,k)
S(n)=S1(,n,0)
S1(n,k)=1 k=n-1
S1(n,k)=1+S1(n,k+1)
S(n)=S1(,n,0)=1+S1(n,1)=1+1+S1(n,2)=…
=1+1+1…+S1(n,n-1)=n=O(n)
-
逻辑层面 实现层面 分析层面
ADT=数据的逻辑结构+数据运算(运算描述) (数据对象 数据关系 基本运算)
逻辑结构映射为存储结构 运算实现为算法
算法分析
例子见代码 Set
#include<iostream>
#include<stdio.h>
using namespace std;
#define MaxSize 20
typedef struct
{
int data[MaxSize];
int length;
} Set;
// 创建集合
void createset(Set &s, int a[], int n)
{
for(int i=0;i<n;i++){
s.data[i]=a[i];
}
s.length=n;
}
// 输出一个集合
void dispset(Set s)
{
for(int i = 0; i< s.length; i++){
printf("%d ",s.data[i]);
}
printf("\n");
}
// 判断e是否在集合中
bool inset(Set s, int e)
{
for(int i=0;i<s.length;i++){
if(s.data[i] == e){
return true;
}
}
return false;
}
// 求集合的并集
void add(Set s1, Set s2, Set &s3)
{
for(int i=0; i<s1.length;i++){
s3.data[i]=s1.data[i];
}
s3.length=s1.length;
for(int i=0;i<s2.length;i++){
if(!inset(s1,s2.data[i])){
s3.data[s3.length]=s2.data[i];
s3.length++;
}
}
}
// 交集
void intersection(Set s1,Set s2,Set &s3)
{
s3.length=0;
for(int i=0;i<s1.length;i++){
if(inset(s2,s1.data[i])){
s3.data[s3.length] = s1.data[i];
s3.length ++ ;
}
}
}
// 差
void sub(Set s1,Set s2,Set &s3)
{
s3.length=0;
for(int i=0;i<s1.length;i++){
if(!inset(s2,s1.data[i])){
s3.data[s3.length] = s1.data[i];
s3.length ++ ;
}
}
}
int main()
{
Set s;
int a[] = {1,2,3};
createset(s,a,3);
dispset(s);
cout<<inset(s,1)<<endl;
Set s2;
int b[] = {3,4};
createset(s2,b,2);
Set s3;
add(s,s2,s3);
dispset(s3);
intersection(s,s2,s3);
dispset(s3);
sub(s,s2,s3);
dispset(s3);
}
```c
#include<iostream>
#include<stdio.h>
using namespace std;
#define MaxSize 20
typedef struct
{
int data[MaxSize];
int length;
} Set;
// 创建集合
void createset(Set &s, int a[], int n)
{
for(int i=0;i<n;i++){
s.data[i]=a[i];
}
s.length=n;
}
// 输出一个集合
void dispset(Set s)
{
for(int i = 0; i< s.length; i++){
printf("%d ",s.data[i]);
}
printf("\n");
}
// 判断e是否在集合中
bool inset(Set s, int e)
{
for(int i=0;i<s.length;i++){
if(s.data[i] == e){
return true;
}
}
return false;
}
// 求集合的并集
void add(Set s1, Set s2, Set &s3)
{
for(int i=0; i<s1.length;i++){
s3.data[i]=s1.data[i];
}
s3.length=s1.length;
for(int i=0;i<s2.length;i++){
if(!inset(s1,s2.data[i])){
s3.data[s3.length]=s2.data[i];
s3.length++;
}
}
}
// 交集
void intersection(Set s1,Set s2,Set &s3)
{
s3.length=0;
for(int i=0;i<s1.length;i++){
if(inset(s2,s1.data[i])){
s3.data[s3.length] = s1.data[i];
s3.length ++ ;
}
}
}
// 差
void sub(Set s1,Set s2,Set &s3)
{
s3.length=0;
for(int i=0;i<s1.length;i++){
if(!inset(s2,s1.data[i])){
s3.data[s3.length] = s1.data[i];
s3.length ++ ;
}
}
}
int main()
{
Set s;
int a[] = {1,2,3};
createset(s,a,3);
dispset(s);
cout<<inset(s,1)<<endl;
Set s2;
int b[] = {3,4};
createset(s2,b,2);
Set s3;
add(s,s2,s3);
dispset(s3);
intersection(s,s2,s3);
dispset(s3);
sub(s,s2,s3);
dispset(s3);
}