1 基本概念
1.1 什么是数据结构
数据结构定义存储数据的方式以及定义需要对这些数据进行的操作,算法实现对这些数据的操作。
- 例1:如何在书架上摆放图书?(1)新书怎么插入?2)如何找到某本指定的书?(问题分解)
- 方式1:随便放 新书插入:O(1);查找书籍:O(N)
- 方式2:按书名拼音字母 新书查入:O(logN) +移动书;查找书籍:O(logN)
- 方式3:书类别+拼音字母 空间如何分配?类别应该分多细? 解决问题方法的效率,跟数据的组织方式有关
-
例2:PrintN 顺序打印从1到N的全部正整数 循环VS递归 解决问题方法的效率,跟空间的利用率有关
-
例3:多项式求值
- 让被测函数重复运行充分多次,使得测出的总的时钟打点间隔充分长,最后计算被测函数平均每次运行的时间即可!
数据结构:数据对象在计算机中的组织方式,数据的逻辑结构(线型结构:1对1;树型结构:1对多;图型结构:多对多),数据的物理存储结构(顺序存储,链式存储);数据对象必定与一系列加在其上的操作相关联;完成这些操作的方法就是算法。
描述数据结构的方式:抽象数据类型
- 数据类型:数据对象集;数据集合相关联的操作集
- 抽象:描述数据类型的方法不依赖于具体实现。与存放数据的机器无关;与数据存储的物理结构无关;与实现操作的算法和编程语言无关。 只关心是什么,不关心如何做到。(接口?)
1.2 什么是算法
一个有限指令集;接受一些输入(有些情况下不需要输入);产生输出;一定再有限步骤之后终止;每一条指令必须:(1)有充分明确的目标,不可以有歧义;(2)计算机能处理的范围之内;(3)描述不应依赖于任何一种计算机语言及具体的实现手段。 空间复杂度S(n)、时间复杂度T(n) 和输入数据的规模相关(问题的规模)
double f(int n, double a[], double x)
{
int i;
double p = a[0];
for (i = 1; i <= n; i++)
{
p += (a[i] * pow(x, i));
}
return p;
}
次乘法
double f(int n, double a[], double x)
{
int i;
double p = a[n];
for (int i = n; i > 0; i--)
{
p = p * x + a[n - 1];
}
return p;
}
次乘法
- 最坏情况复杂度、平均复杂度
- 复杂度的渐进表示法 ——最小上界 ——最大下界
- 一个for循环的时间复杂度等于循环次数乘以循环体代码的复杂度
- if-else 结构的复杂度取决于if的条件判断复杂度和两个分支部分的复杂度,总体复杂度取三者中最大。
1.3 应用实例:最大子列和问题
给定N个整数的序列,求其最大子列和
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
using namespace std;
#define N 100
int Array[N];
void GetRand()
{
//srand(time(0));
for (int i = 0; i < N; i++)
{
Array[i] = rand() % N - N / 2;
}
}
int MaxSubSeqSum1()
{
int ThisSum, MaxSum = 0;
for (int i = 0; i < N; i++)
{
for (int j = i; j < N; j++)
{
ThisSum = 0;
for (int k = i; k <= j; k++)
{
ThisSum += Array[k];
}
if (MaxSum < ThisSum)
{
MaxSum = ThisSum;
}
}
}
return MaxSum;
}
int MaxSubSeqSum2()
{
int ThisSum, MaxSum = 0;
for (int i = 0; i < N; i++)
{
ThisSum = 0;
for (int j = i; j < N; j++)
{
ThisSum += Array[j];
if (ThisSum > MaxSum)
{
MaxSum = ThisSum;
}
}
}
return MaxSum;
}
int MaxSubSeqSum3(int Left, int Right)
{
if (Left >= Right)
{
return Array[Left];
}
int Mid = (Left + Right) / 2;
int LeftSum = MaxSubSeqSum3(Left, Mid);
int RightSum = MaxSubSeqSum3(Mid + 1, Right);
int MaxLeftSumFromMid = 0, Temp = 0;
for (int i = Mid; i >= Left; i--)
{
Temp += Array[i];
if (MaxLeftSumFromMid < Temp)
{
MaxLeftSumFromMid = Temp;
}
}
int MaxRightSumFromMid = 0;
Temp = 0;
for (int i = Mid + 1; i <= Right; i++)
{
Temp += Array[i];
if (MaxRightSumFromMid < Temp)
{
MaxRightSumFromMid = Temp;
}
}
int MaxSumWithMid = MaxLeftSumFromMid + MaxRightSumFromMid;
int MaxSum = LeftSum;
if (MaxSum < RightSum)
{
MaxSum = RightSum;
}
if (MaxSum < MaxSumWithMid)
{
MaxSum = MaxSumWithMid;
}
return MaxSum;
}
int MaxSubSeqSum4()
{
int MaxSum = 0, ThisSum = 0;
for (int i = 0; i < N; i++)
{
ThisSum += Array[i];
if (MaxSum < ThisSum)
{
MaxSum = ThisSum;
}
else if (ThisSum < 0)
{
ThisSum = 0;
}
}
return MaxSum;
}
int main()
{
GetRand();
for (int i = 0; i < N; i++)
{
printf("%d ", Array[i]);
}
printf("\n");
printf("MaxSubSeqSum is %d\n", MaxSubSeqSum4());
}
- MaxSubSeqSum1——
- MaxSubSeqSum2——
- MaxSubSeqSum3——
- MaxSubSeqSum4—— 凡是时间复杂度为的程序,想办法降到O(NlogN)
递归程序复杂度计算方法(以MaxSubSeqNum3为例)