复习数据结构
选择数据结构作为专业课复习的开端,是因为它既是计算机专业的核心基础,也是很多院校考研的重头戏。更重要的是,我深知自己的代码功底还不够扎实,希望通过系统复习,不仅为了应试,更为了真正提升自己的编程思维。
上午:认知建立与工具准备
1.1 数据结构到底是什么?
翻开教材的第一章,首先要搞清楚一个最基本的问题:数据结构到底学的是什么?
简单来说,数据结构研究的是数据的组织方式。就像整理衣柜,衣服可以叠放、可以挂起来、也可以卷起来,不同的组织方式会影响你找衣服的效率。数据也是一样,不同的组织方式(结构)会影响程序的运行效率。
数据结构的三大组成部分:
逻辑结构:数据之间的逻辑关系(集合、线性、树形、图形)
存储结构:数据在计算机中的存储方式(顺序、链式、索引、散列)
数据运算:对数据进行的操作(增删改查、排序等)
1.2 算法的评价:时间复杂度
今天重点攻克了时间复杂度这个概念。说实话,大一学C语言的时候就接触过,但一直似懂非懂。今天才真正明白:
时间复杂度不是代码运行的具体时间,而是随着数据规模n的增长,算法执行时间的增长趋势。
几个常见的复杂度:
O(1):常数阶,无论n多大,执行时间固定
O(n):线性阶,时间与n成正比
O(n²):平方阶,常见于双层循环
O(logn):对数阶,比如二分查找
练习:
c
// 时间复杂度 O(n)
for(i = 0; i < n; i++) {
printf("%d ", i);
}
// 时间复杂度 O(n²)
for(i = 0; i < n; i++) {
for(j = 0; j < n; j++) {
printf("%d ", i+j);
}
}
1.3 建立复习规范
工欲善其事,必先利其器。今天我准备了两本本子:
理论笔记本:记录概念、要点、易错点
代码本:手写所有算法代码,养成手写习惯
决定从今天开始,所有代码都要手写一遍,不能在电脑上复制粘贴。毕竟考试是笔试,手写代码的感觉需要提前培养。
下午:攻克第一个堡垒——顺序表
2.1 顺序表是什么?
顺序表是最基础的数据结构,其实就是用数组实现的线性表。它的特点是:
逻辑上相邻的元素,物理位置上也相邻
支持随机存取:只要知道下标,就能直接访问
插入删除需要移动大量元素
顺序表的定义(C语言):
c
// 静态分配
define MaxSize 50
typedef struct {
int data[MaxSize];
int length;
} SqList;
// 动态分配
typedef struct {
int *data;
int length;
int MaxSize;
} SeqList;
2.2 最容易混淆的概念:位序 vs 下标
今天在这里栽了个跟头,必须重点记录:
位序:元素在逻辑上的位置,从1开始计数
下标:元素在数组中的位置,从0开始计数
第i个元素,存储在data[i-1]中。这个转换看似简单,但在写插入删除操作时,边界条件特别容易出错。
2.3 手撕顺序表的基本操作
初始化操作
c
void InitList(SqList *L) {
L->length = 0; // 空表长度为0
}
插入操作(第一个难点!)
c
bool ListInsert(SqList *L, int i, int e) {
// 1. 判断合法性
if(i < 1 || i > L->length + 1) return false; // i的范围:[1, length+1]
if(L->length >= MaxSize) return false; // 表满
// 2. 移动元素(从后往前)
for(int j = L->length; j >= i; j--) {
L->data[j] = L->data[j-1]; // 后移一位
}
// 3. 插入新元素
L->data[i-1] = e; // 第i个元素存在下标i-1处
// 4. 表长+1
L->length++;
return true;
}
易错点总结:
忘记判断表满
忘记判断插入位置合法性
移动元素的顺序搞反(必须从后往前,否则数据会被覆盖)
下标转换错误:第i个元素存到data[i-1]
删除操作
c
bool ListDelete(SqList *L, int i, int *e) {
// 1. 判断合法性
if(i < 1 || i > L->length) return false;
// 2. 取出被删元素
*e = L->data[i-1];
// 3. 移动元素(从前往后)
for(int j = i; j < L->length; j++) {
L->data[j-1] = L->data[j]; // 前移一位
}
// 4. 表长-1
L->length--;
return true;
}
按值查找
c
int LocateElem(SqList L, int e) {
for(int i = 0; i < L.length; i++) {
if(L.data[i] == e) {
return i+1; // 返回位序
}
}
return 0; // 查找失败
}
2.4 时间复杂度分析
插入操作:平均移动n/2个元素 → O(n)
删除操作:平均移动(n-1)/2个元素 → O(n)
按值查找:平均比较(n+1)/2次 → O(n)
按下标访问:O(1)
这就是顺序表的优点和缺点的根源:随机存取快,插入删除慢。

浙公网安备 33010602011771号