唯一可以确定的是,明天会使我们大吃一惊
数据结构 考研复习版
前言:还是要复习这个了,按理说最拿手,拿来引起一下自己的兴趣吧…
数据结构在学什么?
- 如何用程序代码把现实世界的问题信息化
- 如何用计算机高效地处理这些信息从而创造价值
文章目录
第二章 线性表
数据结构三要素——逻辑结构、数据的运算、存储结构(物理结构)
什么是线性表(Linear list)?——逻辑结构
具有相同类型的n个数据元素的有序数列,其中n为表长,其中n=0时,线性表是一个空表
每个数据元素所占空间一样大
L = (a1, a2 … an),其中ai是线性表中第i个元素在线性表中的位序。
- 注意:线性表位序从1开始,数组下标从0开始。
a1:表头元素
an:表尾元素
除第一个元素外,每个元素有且只有一个直接前驱;除最后一个元素外,每个元素有且只有一个直接后继
线性表的基本操作——数据的运算
- void init(&L) 初始化表L,并分配内存
- void DestoryList(&L) 销毁线性表,且释放内存
- void ListInsert(&L, i, e) 插入操作,在表中第i个元素插入指定元素e
- Type ListDelele(&L, i) 删除操作,删除L表中第i个位置的元素,并用e返回元素的值
- LocateElem(L, e) 按值查找操作,在表L中查找具有给定关键字值的元素
- GetElem(L, i): 按位查找操作,获取表L中第i个元素的值
其它常用操作:
- Length(L):求表长,返回线性表的长度,即L中数据元素的个数
- PrintList(L): 输出操作,按前后顺序输出线性表L中所有元素的值
- Empty(L): 判空操作,若L为空表,则返回True,否则返回False
Tips
-
对数据的操作:创建销毁、增删改查
-
C语言函数定义要清楚(上述是抽象接口)
-
实际开发中,可根据实际需求定义其它操作
-
函数名和命名形式都可以改变
-
&(引用,要知道这是啥,就是要修改调用的参数,要知道引用是C++的概念, C语言这么写↓,即根据地址访问元素,而不是单纯修改形参)
-
#include <stdio.h> void test1(int x){ x = x + 1; } void test2(int* x){ *x = *x + 1; } int main(){ int x = 0; test1(x); printf("%d\n", x); test2(&x); printf("%d", x); return 0; }
-
Why?要实现线性表的基本操作?
- 团队合作编程,你定义的数据结构要方便别人的使用(封装)
- 将常用的操作(运算)封装成函数,避免重复工作,降低出错风险。
顺序表(顺序存储)——逻辑结构
逻辑上相邻的元素,内存里也相邻,每个数据元素所占空间一样大
如何知道一个数据元素大小?
- C语言sizeof(ElemType)
- eg:sizeof(int) = 4B
顺序表的实现——静态分配
// 注意,只能以这种方式定义常量
// int x = 10;
// int a[x];
// 这种定义形式是错误的
#define Maxsize 10
typedef struct {
ElemType data[Maxsize]; //EmemType: 数据类型(int、、、)
int length;
} SqlList;
- 如果“数组”长度满了怎么办?
- 放弃治疗,因为这种方式一旦分配满了就不能更改
- 如果一开始分配太长,又浪费空间
顺序表的实现——动态分配
#define InitSize 10
typedef struct {
ElemType *data; // 指示动态分配数组的指针
int MaxSize;
int Length;
} SqlList;
Tips
C语言中存在malloc, free函数
malloc申请一整片连续的存储空间
malloc函数返回一个指针,需要强制转换为你定义的数据元素类型的指针
L.data = (ElemType *) malloc (sizeof (ElemType) * InitSize);
顺序表的实现
顺序表的特点
- 随机访问:既可以在O(1)时间内找到第i个元素
- 存储密度高,每个节点值存储数据元素
- 拓展容量不方便,即便采用动态分配的方式实现,拓展长度的时间复杂度也比较高
- 插入、删除操作不方便
顺序表的基本操作——插入
在第i个位置的元素插入元素e,i及i之后的元素后移,第i个元素变为e
时间复杂度:
- 最好复杂度:O(1)
- 最坏复杂度:O(n)
- 平均复杂度:O(n)
顺序表的基本操作——删除
删除第i个地方的元素,并返回该元素
时间复杂度:
- 最好复杂度:O(1)
- 最坏复杂度:O(n)
- 平均复杂度:O(n)
顺序表的基本操作——按位查找
直接返回第i个元素
时间复杂度:O(1)(随机存取的特性)
顺序表的基本操作——按值查找
在表中查找具有给定关键字值的元素
注意:C/C++的结构体不能使用“==”进行比较
C++可以重载操作符
时间复杂度:
- 最好:O(1)
- 最差:O(n)
- 平均:O(n)
附:静态顺序表代码:
// 静态顺序表的实现
#include <stdio.h>
#define Maxsize 10
typedef struct {
int data[Maxsize];
int length;
} SqlList;
// 初始化
void Init(SqlList *l) {
(*l).length = 0;
for (int i = 0; i < Maxsize; i++) {
(*l).data[i] = 0;
}
}
//增添长度建议直接放弃治疗
// 插入, 返回0:插入失败;返回1:插入成功
int ListInsert(SqlList *l, int i, int e){
if (i < 1 || i > (*l).length + 1) return 0;
if ((*l).length >= Maxsize) return 0;
for (int j = (*l).length; j >= i; j--)
(*l).data[j] = (*l).data[j - 1];
(*l).data[i - 1] = e;
(*l).length ++;
return 1;
}
// 删除,返回0:删除失败;否则返回删除值
// 注意:这里不考虑删除元素为0的情况!!!
int ListDelete(SqlList *l, int i){
if (i < 1 || i > (*l).length) return 0;
int temp = L.data[i - 1];
for (int j = i; j < (*l).length; j++)
(*l).data[j - 1] = (*l).data[j];
l.length --;
return temp;
}
// 按位查找 返回0:查找失败;否则返回元素值
// 注意:这里不考虑元素为0的情况!!!
int GetELem(SqlList l, int i){
if (i < 1 || i >= l.length) return 0;
return l[i - 1];
}
// 按位查找 返回0:查找失败;否则返回元素位置
int LocateElem(SqlList l, int e){
for (int i = 0; i < l.length; i++)
if (l.data[i] == e)
return i + 1;
return 0;
}
//打印顺序表
void PrintList(SqlList l){
for (int i = 0; i < l.length; i++){
printf("%d ", l.data[i]);
}
}
int main() {
SqlList l;
Init(&l);
PrintList(l);
return 0;
}
动态顺序表代码:
// 静态顺序表的实现
#include <stdio.h>
#include <malloc.h>
#define InitSize 10
typedef struct {
int *data; // 数据
int length; // 当前长度
int maxsize; // 最大容量
} SqlList;
// 初始化
void Init(SqlList *l) {
(*l).length = InitSize;
(*l).maxsize = InitSize;
(*l).data = (int *) malloc (sizeof (int) * (*l).maxsize);
for (int i = 0; i < (*l).maxsize; i++) {
(*l).data[i] = 1;
}
}
//增添长度
void IncreaseList(SqlList *l, int add_length){
int *p = (*l).data;
(*l).data = (int *) malloc(sizeof (int) * ((*l).maxsize + add_length));
(*l).maxsize += add_length;
for (int i = 0; i < (*l).maxsize; i++){
if (i < (*l).length) (*l).data[i] = p[i];
else (*l).data[i] = 0;
}
}
//打印顺序表
void PrintList(SqlList l){
for (int i = 0; i < l.length; i++){
printf("%d ", l.data[i]);
}
}
int main() {
SqlList l;
Init(&l);
IncreaseList(&l, 5);
PrintList(l);
return 0;
}