数据结构(1)

一、

  1. 指针未初始化:•buf 数组中的每个元素需要初始化为一个有效的字符数组指针。否则,strcpy 将尝试写入未定义的内存区域,导致段错误。•解决方案:在使用 buf 数组之前,确保每个元素都指向一个有效的字符数组。

  2. 内存分配:•在 buf 数组中存储字符串之前,需要为每个元素分配足够的内存。•解决方案:使用 malloc 或 calloc 为每个 buf 元素分配内存。

定义指针数组本身并不会自动分配内存。指针数组只是一个数组,其中每个元素都是一个指针。每个指针需要单独分配内存,以便能够存储实际的数据。

指针数组指向已经开好的空间,和指针效果一样,没有存储数据的空间,保存数据需要二维数组

指针是要操作数据,数据已经保存好

  1. 数组越界:•是一种运行时错误,可能导致程序崩溃或未定义行为。•通常由于索引超出数组的有效范围引起。•例如,arr[5] 对于一个大小为 5 的数组 arr 就是越界。

  2. 内存泄漏:•是一种资源管理问题,导致分配的内存无法被释放。•通常由于忘记释放动态分配的内存引起。•例如,malloc 分配的内存没有通过 free 释放

3.结构体对齐:

结构体按照其最长成员大小对齐,意味着最终的大小必须是最长成员大小的整数倍;

结构体成员按照结构体成员声明先后次序依次存放,并且每个成员的首字节放置的位置必须能够整除成员的字节数;

如果结构体某个成员的字节数大于CPU的字节数,则最长按照CPU的字节数对齐;

用预处理命令#pragma pack(n) 可以强制编译器按照指定的n来对齐,合法的n的数值分别是1、2、4、8、16。

按数组名的基类型对齐

二、

线性结构,前面最多一个前驱元素,后面最多一个后继元素

内存碎片1. 外部碎片(External Fragmentation):•当多个不连续的小块内存空间之间没有足够的连续空间来满足新的内存分配请求时,就产生了外部碎片。•即使总的可用内存空间足够,但由于这些空间分散在不同的地方,无法合并成一个连续的空间,导致无法分配给新的请求。•例如,假设有以下内存布局:(数组)

  1. 内部碎片(Internal Fragmentation):•内部分片是指分配给某个程序的内存块中有未使用的部分。•这通常是由于内存分配算法分配的内存块大于实际所需,导致剩余的部分无法使用。•例如,假设内存分配器分配了 256KB 的内存给一个只需要 128KB 的程序,剩下的 128KB 就构成了内部碎片。(结构体)

内存碎片的影响内存碎片会对程序和系统的性能产生负面影响,包括:•内存利用率降低:由于碎片的存在,无法有效地利用所有可用内存。•分配效率下降:分配新的内存请求时,可能需要花费更多的时间来寻找合适的内存块。•性能下降:频繁的内存分配和释放操作会导致系统性下降。

解决内存碎片的方法1. 紧凑化(Compaction):•移动已分配的内存块,使其集中在一起,从而释放出连续的内存空间。•这种方法在一些内存管理系统中实现,但可能会引入额外的开销。2. 内存池(Memory Pooling):•预先分配一大块内存,然后从中分配小块内存给程序。•通过内存池管理可以减少内存碎片,提高内存分配效率。3. 更好的内存分配算法:•选择更高效的内存分配算法,如最佳适应算法(Best Fit)、首次适应算法(First Fit)等。•这些算法在分配内存时尽量选择最合适的块,从而减少碎片。4. 内存管理工具:•使用内存管理工具(如 Valgrind、glibc 等)来检测和管理内存使用情况,优化内存分配策略。示例假设一个简单的内存管理场景,展示内存碎片如何发生以及如何解决:场景描述•初始内存布局为一块连续的大内存空间。•分配几个不连续的小块内存。•释放一些内存块。

哈希存储(Hash Storage)和索引存储(Indexed Storage)是两种常用的数据存储方式,每种方式都有其特点和适用场景。下面我们分别介绍这两种存储方式的概念、工作原理及其优缺点。

哈希存储(Hash Storage)概念哈希存储使用哈希函数将数据项映射到一个固定大小的索引空间中。哈希函数通常将任意长度的输入转换为固定长度的输出,这个输出称为哈希值或哈希码。哈希表是一种常用的数据结构,用于实现哈希存储。工作原理1. 哈希函数:将数据项(key)映射到一个固定大小的索引空间。2. 存储位置:计算出的哈希值决定了数据项在存储结构中的位置。3. 冲突处理:当两个不同的数据项映射到同一个位置时,称为哈希冲突。通常使用开放寻址法(如线性探测、二次探测、双重散列等)或链地址法(如拉链法)来解决冲突。优点•快速查找:平均情况下,哈希表的查找时间复杂度为 O(1)。•插入和删除操作快:哈希表支持快速的插入和删除操作,平均时间复杂度也为 O(1)。•空间利用率高:哈希表的空间利用率相对较高,因为数据项直接映射到存储位置。缺点•哈希冲突:如果哈希函数设计不当,容易导致哈希冲突,影响性能。•负载因子:负载因子(装填因子)过高时,哈希表的性能会下降。•扩展性:当哈希表需要扩容时,可能需要重新哈希所有数据项。

索引存储(Indexed Storage)概念索引存储通过建立一个索引来加速数据的查找。索引通常是一个独立的数据结构,如 B 树、B+树、红黑树等,它将数据项的 key 映射到数据项的位置。工作原理1. 索引结构:索引结构通常是一个树形结构,每个节点包含若干个 key 和指向数据项的指针。2. 查找操作:通过索引结构中的 key 快速定位到数据项的位置。3. 维护索引:每次插入或删除数据项时,都需要更新索引结构。优点•高效查找:索引结构(如 B 树、B+树)支持高效的查找操作,时间复杂度通常为 O(log n)。•有序存储:索引通常保持有序,便于范围查询。•支持多种操作:除了查找,还支持插入、删除等多种操作。缺点•额外的存储开销:索引结构本身需要额外的存储空间。•维护成本:每次插入或删除数据项时,都需要维护索引结构,增加了操作的复杂性和开销。•不适用于小数据集:对于较小的数据集,索引的开销可能大于直接遍历数据集的成本。应用场景比较哈希存储•适用于大量数据的快速查找:当需要快速查找大量数据时,哈希表是一个很好的选择。•适用于无序数据:哈希表不保持数据的有序性,适用于不需要排序的数据集。•适用于缓存:哈希表常用于缓存数据,以提高数据访问速度。索引存储•适用于数据库系统:数据库系统广泛使用索引结构(如 B 树、B+树)来加速数据查找。•适用于有序数据:当数据需要保持有序时,索引结构是一个好的选择。•适用于频繁更新的数据集:尽管索引需要维护,但对于频繁更新的数据集,索引仍然可以提供高效的查询。(如进程间内存共享运用红黑树获得key值分配唯一内存,红黑树本身不是专门为进程间内存共享设计的数据结构,但它可以在共享内存等机制的基础上实现进程间共享。在使用红黑树进行进程间共享时,需要注意同步问题,以避免数据竞争和不一致。通常使用信号量或互斥锁来保护共享内存中的数据结构)

高内聚(一个模块只干一个事)低耦合(函数关联度低)

面向过程:第一步干什么第二步干什么(打开冰箱门,装冰箱,关闭冰箱门)

面向对象:用什么,干什么(定义对象和行为之后,装什么都可以)

数组:1. 空间连续

  1. 访问数据方便(O(1))

  2. 插入和删除需要移动大量数据

  3. 预分配内存空间

链表:1. 空间不连续

  1. 访问数据需要遍历(O(n))

  2. 插入和删除方便

  3. 不需要预分配

  4. 创建链表

  5. 插入数据----》头插/尾插

  6. 删除数据----》头删/尾删

  7. 修改 修改旧数据为新数据

  8. 查找 根据关键字,查找节点,返回找到的节点的地址

  9. 销毁

线性结构:

顺序表-----》数组

链式表-----》链表

相关推荐
tinker在coding14 分钟前
Coding Caprice - Linked-List 1
算法·leetcode
XH华5 小时前
初识C语言之二维数组(下)
c语言·算法
南宫生5 小时前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论
不想当程序猿_5 小时前
【蓝桥杯每日一题】求和——前缀和
算法·前缀和·蓝桥杯
落魄君子5 小时前
GA-BP分类-遗传算法(Genetic Algorithm)和反向传播算法(Backpropagation)
算法·分类·数据挖掘
菜鸡中的奋斗鸡→挣扎鸡5 小时前
滑动窗口 + 算法复习
数据结构·算法
Lenyiin6 小时前
第146场双周赛:统计符合条件长度为3的子数组数目、统计异或值为给定值的路径数目、判断网格图能否被切割成块、唯一中间众数子序列 Ⅰ
c++·算法·leetcode·周赛·lenyiin
郭wes代码6 小时前
Cmd命令大全(万字详细版)
python·算法·小程序
scan7246 小时前
LILAC采样算法
人工智能·算法·机器学习
菌菌的快乐生活6 小时前
理解支持向量机
算法·机器学习·支持向量机