今天开始一个新的专题:数据结构当然,不仅仅适用于学习也适用于408考研。
那么提起数据结构
思维导图:总结如下:·

1.初识顺序表与链表
首先呢我们要明白,数据结构有物理结构,也有逻辑结构

物理结构
就是电脑实际的结构,链式,非链式,索引,散列
eg:
链式结构(Linked Structure)
例子:火车车厢
想象一列火车,每节车厢都连接在一起。每一节车厢(数据节点)都有一个链接(指针),连接到下一节车厢。这就是链式结构。要找到某一节车厢,你需要从第一节车厢开始,依次通过连接找到目标车厢。
非链式结构(Non-Linked Structure)
例子:书架
现在想象一个书架,上面整齐地排列着书籍。每本书(数据项)都直接放在一个固定的位置。你可以通过书的位置直接找到它,而不需要从第一本书开始逐本寻找。这就是非链式结构。
索引(Index)
例子:图书馆的目录卡片
想象一个图书馆,每本书在书架上的位置都通过一张目录卡片来记录。你可以先查找目录卡片(索引),找到书的位置,然后直接去拿书。这种方法提高了查找效率,因为你不需要在书架上一本本地找。
散列(Hashing)
**例子:钥匙和钥匙扣】
想象你有一个钥匙扣,上面挂着多把钥匙。每把钥匙上都有一个标签(哈希值),标明它对应的锁(数据位置)。当你要找某一把钥匙时,你通过钥匙上的标签很快就能找到它。这就是散列的基本原理,通过一个哈希函数(标签生成方式),可以快速找到数据的位置。
逻辑结构
简单讲就是脑子里面想的,分为线性与非线性
线性结构(Linear Structure) 例子:排队买票
想象你在电影院排队买票。大家一个接一个排成一条直线,这就是线性结构。每个人的位置是有序的,前面有一个人,后面也有一个人(除了队首和队尾)。
实际数据结构:数组和链表
- 数组:就像排队,每个人(元素)都有固定的位置(索引)。你可以通过位置(索引)快速找到任何一个人(元素)。
- 链表:也是线性结构,但每个人(节点)手里都有一个纸条,写着下一个人的名字(指针)。你要找到某个人,需要从第一个人开始,一个个问过去。
-
栈(Stack)
例子:书堆
想象一堆书,你只能从顶部添加或移除书。这就是栈的概念。栈是一种“后进先出”(Last In, First Out, LIFO)的结构。最新放进去的元素最先被取出来。
实际数据结构:栈
- 操作:
- 压栈(Push):在栈顶添加一个元素。
- 出栈(Pop):从栈顶移除一个元素。
- 栈顶(Top/Peek):查看栈顶的元素而不移除它。
-
队列(Queue)
例子:排队买票
想象在电影院排队买票,最早来的人最先买到票,最晚来的人最后买到票。这就是队列的概念。队列是一种“先进先出”(First In, First Out, FIFO)的结构。最先进入队列的元素最先被取出。
实际数据结构:队列
- 操作:
- 入队(Enqueue):在队尾添加一个元素。
- 出队(Dequeue):从队首移除一个元素。
- 队首(Front):查看队首的元素而不移除它。
非线性结构(Non-Linear Structure) 例子:家谱图
想象一个家谱图,它展示了一个家族的成员关系。祖先在上,后代在下,分支可能有很多。这就是非线性结构。每个人(节点)可以有多个孩子(指向多个节点)。
实际数据结构:树和图
- 树:就像家谱图,每个节点可以有多个子节点(孩子),但只有一个父节点(除了根节点)。例如,二叉树是一种特殊的树,每个节点最多有两个子节点。
- 图:比家谱图更复杂,每个节点可以和多个节点有连接(边)。例如,城市地图就是一个图结构,城市是节点,道路是边。
总结如下:
408常考题目:判断是逻辑还是物理结构.
技巧:指数据元素之间的逻辑关系,与数据的存储无关,独立于计算机的用于判断逻辑。
注意:哈希表是物理结构,与存储结构有关,循环队列也是。
关于站和队列,则是逻辑结构。
2.顺序表
开始线性表的学习了。
导图:
什么是顺序表呢?
类似于数组;
-
静态分配
-
类型定义
typedef struct { ElemType data[MaxSize]; int length; } SqList; -
typedef struct {...} SqList;
- 这段代码定义了一个结构体,并通过
typedef给它起了一个别名SqList。这样你可以使用SqList来声明这种结构体类型的变量,而不需要每次都写struct {...}。
- 这段代码定义了一个结构体,并通过
-
ElemType data[MaxSize];
data是一个数组,它的类型是ElemType,数组的大小是MaxSize。ElemType是一个占位符,通常在实际代码中会被替换为具体的数据类型,例如int、float或者自定义的数据类型。MaxSize是一个宏定义或常量,表示顺序表可以容纳的最大元素数量。
-
int length;
length用来记录顺序表当前的长度,即顺序表中实际包含的元素个数。
-
-
动态分配(好好讲讲)

struct SqList {
ElemType* data; // 指向动态分配数组的指针
int length; // 当前顺序表的长度
int maxSize; // 顺序表的最大容量
};
注意:这个可和链表不一样 注意:动态分配不是链式存储,它同样属于顺序存储结构,物理结构没有变化,只是分配的空间大小可以在运行时动态决定
具体用法:
1.初始化顺序表
// 构造函数,初始化顺序表
SqList(int maxSize) : maxSize(maxSize), length(0)
{
data = new ElemType[maxSize];
}
2.增加
// 增加元素到顺序表尾部
void insertElem(ElemType elem)
{ if (length >= maxSize)
{
throw std::overflow_error("顺序表已满,无法插入元素。");
}
data[length] = elem;
length++; }
// 在指定位置插入元素
void insertElemAt(int pos, ElemType elem) {
if (pos < 0 || pos > length) { // 注意:这里 pos 可以等于 length,表示在末尾插入
throw std::out_of_range("位置非法,无法插入元素。");
}
if (length >= maxSize) {
throw std::overflow_error("顺序表已满,无法插入元素。");
}
for (int i = length; i > pos; i--) {
data[i] = data[i - 1];
}
data[pos] = elem;
length++;
}
408里面 长度为n
注意:线性表元素序号从1开始(逻辑位序和物理位序相差1)
合法插入位置:1 <= i <= n+1(表尾)
代码改为: void insertElemAt(int pos, ElemType elem) {
if (pos < 1 || pos > length + 1) { // 合法位置范围为 1 <= pos <= length + 1
throw std::out_of_range("位置非法,无法插入元素。");
}
if (length >= maxSize) {
throw std::overflow_error("顺序表已满,无法插入元素。");
}
for (int i = length; i >= pos; i--) {
data[i] = data[i - 1];
}
data[pos - 1] = elem; // 将位置 pos 转换为索引 pos-1
length++;
}
3.删除
// 删除顺序表中指定位置的元素
void deleteElem(int pos) {
if (pos < 0 || pos >= length) {
throw std::out_of_range("位置非法,无法删除元素。");
}
for (int i = pos; i < length - 1; i++) {
data[i] = data[i + 1];
}
length--;
}
408里面 长度为n
注意:合法删除位置:1 <= i <= n
为了符合删除操作的合法位置约束(1 <= i <= n),需要对删除元素的位置进行适当的调整。C++ 中数组的索引从 0 开始,但在实际使用中,位置可能从 1 开始,因此需要进行相应的转换。在 C++ 实现中,我们需要对位置参数进行减1操作,以使其适应 C++ 中的数组索引。
void deleteElem(int pos) {
if (pos < 1 || pos > length) { // 合法位置范围为 1 <= pos <= length
throw std::out_of_range("位置非法,无法删除元素。");
}
for (int i = pos - 1; i < length - 1; i++) {
data[i] = data[i + 1];
}
length--;
}
4.修改
// 修改顺序表中指定位置的元素
void updateElem(int pos, ElemType newElem) {
if (pos < 0 || pos >= le

最低0.47元/天 解锁文章

被折叠的 条评论
为什么被折叠?



