一、数据结构概论
1.抽象数据类型(Abstract Data Type )
(1)数据类型:
- 数据对象集
- 数据集合相关联的操作集
(2)抽象:描述数据类型的方法不依赖于具体实现
- 与存放数据的机器无关
- 与数据存储的物理结构无关
- 与实现操作的算法和编程语言均无关
(3)即:只描述数据对象集和相关操作集 只描述数据对象集和相关操作集“ 是什么”,并不涉及 ,并不涉及“ 如何做到”的问题。
2.复杂度的渐进表示法
二、几个小算法
1.计算多项式的值(秦九韶算法)
变形之后:
#include<cstdio>
double f(int n, double a[], double x) {
double p = a[n];
for (int i = n; i > 0; i--)
p = a[i - 1] + x * p;
return p;
}
2.clock() 函数用法示例:
(1)原理:捕捉从程序开始运行到clock()被调用时所耗费的时间。这个时间单位是被调用时所耗费的时间。这个时间单位是clock tick ,即“ 时钟打点”。常数CLK_TCK( 或CLOCKS_PER_SEC)
(2)一个应用:计算函数平均运行时间。让被测函数 重复运行充分多次,使得测出的总的时钟打点间隔充分长,最后计算被测函数充分多次,使得测出的总的时钟打点间隔充分长,最后计算被测函数平均每次运行的时间即可。
#include<cstdio>
#include<ctime>
using namespace std;
clock_t start, stop;
double duration;
void MyFunction(){}
int main() {
start = clock();
MyFunction();
stop = clock();
duration = ((double)(stop - start)) / CLK_TCK;
return 0;
}
3.最大子列和问题:
(1)描述:给定K个整数组成的序列{ },“连续子列”被定义为{ Ni, Ni+1, ..., Nj },其中 1≤i≤j≤K。“最大子列和”则被定义为所有连续子列元素的和中最大者。
法一:暴力枚举(时间复杂度为O(n ^ 2))
#include<cstdio>
int MaxSubseqSum(int A[], int N) {
int ThisSum, MaxSum = 0;
int i, j;
for (int i = 0; i < N; i++) {
ThisSum = 0;
for (int j = i; j < N; j++) {
ThisSum += A[j];
if (ThisSum > MaxSum) MaxSum = ThisSum;
}
}
return MaxSum;
}
法二:分治法(时间复杂度O(n * log n))
#include<cstdio>
#include<algorithm>
using namespace std;
int DivideAndConquer(int List[], int left, int right) {
int MaxLeftSum, MaxRightSum; /* 存放左右子问题的解 */
int MaxLeftBorderSum = 0, MaxRightBorderSum = 0; /*存放跨分界线的结果*/
int LeftBorderSum = 0, RightBorderSum = 0;
if (right - left <= 1) {
if (List[left] > 0) return List[left];
else return 0;
}
int center = (left + right) / 2;
MaxLeftSum = DivideAndConquer(List, left, center);
MaxRightSum = DivideAndConquer(List, center, right);
for (int i = center; i >= left; i--) {
LeftBorderSum += List[i];
MaxLeftBorderSum = max(MaxLeftBorderSum, LeftBorderSum);
}
for (int i = center + 1; i < right; i++) {
RightBorderSum += List[i];
MaxRightBorderSum = max(MaxRightBorderSum, RightBorderSum);
}
return max(max(MaxLeftSum, MaxRightSum), MaxLeftBorderSum + MaxRightBorderSum);
}
法三:在线处理(时间复杂度为O(n))
因为读入数据时间复杂度是线性的,因此认为复杂度是线性的已经可以了。
#include<cstdio>
int MaxSubseqSum(int A[], int N) {
int ThisSum = 0, MaxSum = 0;
int i;
for (int i = 0; i < N; i++) {
ThisSum += A[i];
if (ThisSum > MaxSum) MaxSum = ThisSum;
else if (ThisSum < 0) ThisSum = 0;
}
return MaxSum;
}
4.计算组合数
(1)递归算法
#include<cstdio>
int combinat(int m, int n) {
if (n == 0 || m == n) return 1;
return combinat(m - 1, n) + combinat(m - 1, n - 1);
}
(2)动态规划
#include<cstdio>
const int maxSize = 100;
int combinate(int m, int n) {
int C[maxSize][maxSize];
if (n == 0 || m == n) return 1;
for (int i = 1; i <= m; i++) C[i][0] = C[i][i] = 1;
for (int i = 1; i <= m; i++) {
for (int j = 1; j < i; j++) {
//你会发现i = 1时并不会进入第二重循环,因此也不会算C[0][1]的值
C[i][j] = C[i - 1][j] + C[i - 1][j - 1];
}
}
return C[m][n];
}