数据结构基础(2)
数据结构基础(2)
目录
线性表的定义:
线性表是具有相同数据类型的n(n>= 0)个数据元素的有限序列,其中n为表长,当n = 0时线性表是一个空表。
注意:
- 每个数据元素所占空间是一样大的
- 是有次序的
- 线性表中的位序是从1开始的,数组下标是从0开始的
线性表的基本操作:
- 初始化表:构造一个空的线性表,分配内存空间
- 销毁操作:销毁线性表,并释放线性表L所占用的内存空间
- 插入操作:在表L中的第i个位置上插入指定元素e
- 删除操作:删除表L中第i个位置的元素,并用e返回删除元素的值(需引用符号)
- 按值查找操作:在表L中查找具有给定关键字的元素
- 按位查找操作:获取表L中第i个位置的元素的值
- 其他常用操作:
- 求表长:返回线性表L的长度,即L中数据元素的个数
- 输出操作:按前后顺序输出线性表L的所有元素值
- 判空操作:若L位空表,则返回true,否则返回false
tips:
- 创销增删改查
- 什么时候要传入引用"&"--对参数的修改结果需要"带回来"
顺序表的定义:
顺序表--用顺序存储的方式实现线性表
如何知道一个数据元素的大小?
用sizeof(ElemType)
顺序表的实现--静态分配(大小不可改)
例如:
#define MaxSize 10 //定义最大长度
typedef struct {
ElemType data[MaxSize]; //用静态的"数组"存放数据元素
int length; //顺序表的当前长度
}SqList; //顺序表的类型定义(静态分配方式)
顺序表的实现--动态分配
#define InitSize 10 //顺序表初始化长度
typedef struct {
ElemType *data; //指示动态分配数组的指针
int MaxSize; //顺序表的最大容量
int length; //顺序表的当前长度
}SeqList; //顺序表的类型定义(静态分配方式)
key: 动态申请和释放内存空间
c-- malloc,free函数
c++ -- new,delete 关键字
举例:
#include <stdlib.h>
#define InitSize 10 // 默认的最大长度
typedef struct {
int *data; // 指示动态分配数组的指针
int MaxSize; // 顺序表的最大容量
int length; // 顺序表的当前长度
} SeqList;
// 初始化顺序表
void InitList(SeqList &L) {
// 用 malloc 函数申请一片连续的存储空间
L.data = (int *)malloc(InitSize * sizeof(int));
L.length = 0;
L.MaxSize = InitSize;
}
// 增加动态数组的长度
void IncreaseSize(SeqList &L, int len) {
int *p = L.data;
L.data = (int *)malloc((L.MaxSize + len) * sizeof(int));
for (int i = 0; i < L.length; i++) {
L.data[i] = p[i]; // 将数据复制到新区域
}
L.MaxSize = L.MaxSize + len; // 顺序表最大长度增加 len
free(p); // 释放原来的内存空间
}
int main() {
SeqList L; // 声明一个顺序表
InitList(L); // 初始化顺序表
//...往顺序表中随便插入几个元素...
IncreaseSize(L, 5);
return 0;
}
顺序表的特点:
- 随机访问,即可以在O(1)时间内找到第i个元素
- 存储密度高,每个节点只存储数据元素
- 拓展容量不方便(即便采用动态分配的方式实现,拓展长度的时间复杂度也比较高)
- 插入、删除操作不方便,需要移动大量元素
顺序表的基本操作--插入
ListInsert(&L,i,e) : 插入操作:在表L中的第i个位置上插入指定元素e
#define MaxSize 10 // 定义最大长度
typedef struct {
int data[MaxSize]; // 用静态的“数组”存放数据元素
int length; // 顺序表的当前长度
} SqList; // 顺序表的类型定义
bool ListInsert(SqList &L, int i, int e) {
// 插入位置 i 应该满足 1 <= i <= L.length + 1,这样才能保证插入到合理位置
if (i < 1 || i > L.length + 1) {
// 位置不合法,无法插入,返回 false
return false;
}
// 如果当前顺序表的长度已经达到了最大容量 MaxSize,就不能再插入新元素了
if (L.length >= MaxSize) {
return false;
}
for (int j = L.length; j >= i; j--) {
L.data[j] = L.data[j - 1];
}
L.data[i - 1] = e; // 将新元素 e 放到腾出的位置(也就是数组下标为 i - 1 的地方 )
L.length++;
return true;
}
int main() {
SqList L; // 声明一个顺序表
InitList(L); // 初始化顺序表(需补充 InitList 函数定义才能正常运行)
//...此处省略一些代码,插入几个元素
ListInsert(L, 3, 3);
return 0;
}
注意位序,数组下标的关系,并从后面的元素依次移动
分析时间复杂度:
最好情况:新元素插入到表尾,不需要移动元素 O(1)
最坏情况:新元素插入到表头,需要将原有的n个元素全都向后移动,O(n)
平均情况:O(n)
顺序表的基本操作--删除
ListDelete(&L,&e) : 删除操作:删除表L中第i个位置的元素,并用e返回删除元素的值
#define MaxSize 100 // 假设最大长度,可根据实际调整
typedef struct {
int data[MaxSize];
int length;
} SqList;
// 函数声明(如果在实际代码中,若函数定义在调用之后,可能需要声明,这里按逻辑提取)
bool ListDelete(SqList &L, int i, int &e);
void InitList(SqList &L); // 该函数需补充具体实现
bool ListDelete(SqList &L, int i, int &e) {
if (i < 1 || i > L.length) // 判断 i 的范围是否有效
return false;
e = L.data[i - 1]; // 将被删除的元素赋值给 e
for (int j = i; j < L.length; j++) // 将第 i 个位置后的元素前移
L.data[j - 1] = L.data[j];
L.length--; // 线性表长度减 1
return true;
}
int main() {
SqList L; // 声明一个顺序表
InitList(L); // 初始化顺序表(需补充 InitList 函数实现)
//...此处省略一些代码,插入几个元素
int e = -1; // 用变量 e 把删除的元素“带回来”
if (ListDelete(L, 3, e))
printf("已删除第 3 个元素,删除元素值为=%d\n", e);
else
printf("位序 i 不合法,删除失败\n");
return 0;
}
注意位序,数组下标的关系,并从前面的元素依次移动
分析时间复杂度:
最好情况:删除表尾元素,不需要移动元素 O(1)
最坏情况:删除表头,需要将原有的n-1个元素全都向前移动,O(n)
平均情况:O(n)
顺序表的按位查找--静态分配
GetElem(L,i) : 按位查找操作,获取表 L 中第 i 个位置的元素的值
#define MaxSize 10 // 定义最大长度
typedef struct {
ElemType data[MaxSize]; // 用静态的“数组”存放数据元素
int length; // 顺序表的当前长度
} SqList; // 顺序表的类型定义(静态分配方式)
ElemType GetElem(SqList L, int i) {
return L.data[i - 1];
}
顺序表的按位查找--动态分配
GetElem(L,i) : 按位查找操作,获取表 L 中第 i 个位置的元素的值
#define InitSize 10
typedef struct {
ElemType *data;
int MaxSize;
int length;
} SeqList;
ElemType GetElem(SeqList L, int i) {
return L.data[i - 1];
}
时间复杂度:O(1)
顺序表的按值查找--动态分配
typedef struct {
int *data; // 指示动态分配数组的指针
int MaxSize; // 顺序表的最大容量
int length; // 顺序表的当前长度
} SeqList;
// 在顺序表 L 中查找第一个元素值等于 e 的元素,并返回其位序
int LocateElem(SeqList L, int e) {
for (int i = 0; i < L.length; i++)
if (L.data[i] == e)
return i + 1;
return 0;
}
注意:在C语言中,结构体的比较不能直接用"== "来比较
时间复杂度:
最好情况:目标元素在表头 O(1)
最坏情况:目标元素在表尾O(n)
平均情况:O(n)

浙公网安备 33010602011771号