目录
- 数据的逻辑结构
- 数据的物理结构
- 算法的五大特性
- 好的算法目标
- 时间复杂度与空间复杂度
- 线性表的顺序存储(顺序表)
6.1 静态分配
6.2 动态分配
6.3 基本操作及时间复杂度
一、数据的逻辑结构
数据的逻辑结构描述数据元素之间的逻辑关系,分为以下四类:
1. 集合结构
- 特点:元素仅属于同一集合,无其他关系。
- 示例:学生成绩表中的所有学生。
2. 线性结构
- 特点:元素间存在一对一关系。
- 除首元素外,每个元素有唯一前驱;
- 除尾元素外,每个元素有唯一后继。
- 示例:数组、链表。
3. 树形结构
- 特点:元素间存在一对多关系。
- 示例:文件系统目录、组织架构。
4. 图形结构
- 特点:元素间存在多对多关系。
- 示例:社交网络、交通网络。
二、数据的物理结构
数据的物理结构描述数据在计算机中的存储方式,分为以下四类:
存储方式 | 特点 |
---|---|
顺序存储 | 逻辑相邻的元素物理位置相邻(如数组)。 |
链式存储 | 逻辑相邻的元素物理位置可不相邻,通过指针关联(如链表)。 |
索引存储 | 建立索引表,通过关键字快速定位(如数据库索引)。 |
散列存储 | 根据关键字直接计算存储地址(哈希表)。 |
三、算法的五大特性
- 有穷性:算法必须在有限步骤内终止。
- 确定性:相同输入必得相同输出,无歧义。
- 可行性:每一步操作可通过基本运算实现。
- 输入:0个或多个输入。
- 输出:至少1个输出。
四、好的算法目标
- 正确性 ✅:算法能正确解决问题.
- 可读性 📖:代码易于理解与维护.
- 健壮性 🛡️:对非法输入有合理处理机制.
- 高效性 ⚡:时间与空间复杂度低.
五、时间复杂度与空间复杂度
1. 时间复杂度
- 计算规则:
- 保留最高阶项,忽略系数(例如,
T(n) = 3n + 3 → O(n)
)。 - 嵌套循环关注最深层循环次数.
- 保留最高阶项,忽略系数(例如,
- 常见复杂度排序:
O(1) < O(log n) < O(n) < O(n log n) < O(n²) < O(2ⁿ) < O(n!)
示例代码:
void fun(int n) {
int i = 1;
while (i <= n) {
i++;
printf("hello");
}
printf("linux");
}
// 时间复杂度 T(n) = 3n + 3 → O(n)
2. 空间复杂度
- 定义:算法运行所需的辅助空间大小.
- 原地工作:空间复杂度为
O(1)
(例如,变量交换).
六、线性表的顺序存储(顺序表)
顺序表通过数组实现,支持快速随机访问,但增删操作效率较低.
静态分配
#include <stdio.h>
#define MaxSize 10
typedef struct {
int data[MaxSize];
int length;
} SqList;
// 初始化
void InitList(SqList *L) {
for (int i = 0; i < MaxSize; i++)
L->data[i] = 0;
L->length = 0;
}
int main() {
SqList L;
InitList(&L);
return 0;
}
动态分配
#include <stdio.h>
#include <stdlib.h>
#define InitSize 10
typedef struct {
int *data;
int MaxSize;
int length;
} SqList;
// 初始化
void InitList(SqList *L) {
L->data = (int *)malloc(InitSize * sizeof(int));
L->MaxSize = InitSize;
L->length = 0;
}
// 扩容
void IncreaseSize(SqList *L, int len) {
L->data = (int *)realloc(L->data, (L->MaxSize + len) * sizeof(int));
L->MaxSize += len;
}
int main() {
SqList L;
InitList(&L);
IncreaseSize(&L, 5);
return 0;
}
基本操作及时间复杂度
操作 | 时间复杂度 | 说明 |
---|---|---|
按位查找 | O(1) | 直接通过下标访问元素. |
按值查找 | O(n) | 遍历数组查找目标值. |
插入 | O(n) | 需移动后续元素(平均n/2次). |
删除 | O(n) | 需移动后续元素. |
代码示例(插入与删除):
// 插入元素
bool ListInsert(SqList *L, int i, int e) {
if (i < 0 || i > L->length || L->length >= L->MaxSize)
return false;
for (int j = L->length; j > i; j--)
L->data[j] = L->data[j - 1];
L->data[i] = e;
L->length++;
return true;
}
// 删除元素
bool ListDelete(SqList *L, int i, int *e) {
if (i < 0 || i >= L->length)
return false;
*e = L->data[i];
for (int j = i; j < L->length - 1; j++)
L->data[j] = L->data[j + 1];
L->length--;
return true;
}