数据结构–顺序表的定义
知识总览
顺序表
\color{red}顺序表
顺序表―一用
顺序存储
\color{red}顺序存储
顺序存储的方式实现线性表
顺序存储。把
逻辑上相邻
\color{red}逻辑上相邻
逻辑上相邻的元素存储在
物理位置上也相邻
\color{red}物理位置上也相邻
物理位置上也相邻的存储单元中,元素之间的关系由存储单元的邻接关系来体现。
线性表是具有 相同 \color{red}相同 相同数据类型的n( n ≥ 0 n\ge0 n≥0)个 数据元素 \color{purple}数据元素 数据元素的有限序列
eg:
typedef struct
{
int num;
int people;
} Customer
如何知道一个数据元素大小?
在C语言中我们可以使用sizeof(ElemType)
eg:
sizeof(int) = 4B
sizeof(Customer) = 8B
静态分配
下面展示一个静态分配顺序表的C代码
#include <stdio.h>
#define MaxSize 10
typedef struct
{
int date[MaxSize];
int len;
}SqList;
void InitList(SqList &L) // 初始化
{
for (int i = 0; i < MaxSize; i++)
L.date[i] = 0;
L.len = 0;
}
int main()
{
SqList L;
InitList(L);
// ...
return 0;
}
ps:
初始化很重要
因为内存中会有遗留的藏数据
\color{purple}因为内存中会有遗留的藏数据
因为内存中会有遗留的藏数据
两个问题
如果“数组”存满了怎么办?
答:无可救药,没有办法,顺序表的表长刚开始确定后就无法更改(存储空间是静态的)。
如果刚开始就声明一个很大的内存空间呢?存在什么问题?
答:浪费空间
动态分配
#define Initsize 10
typedef struct
{
lemType *data; //指示动态分配数组的指针
int MaxSize; //顺序表的最大容量
int length; //顺序表的当前长度
}SeqList;
C关于申请与释放内存空间的两个函数
malloc和free函数是C语言中动态内存分配的函数。动态内存分配是指在程序运行时,根据需要动态地分配内存空间,以便存储数据。与之相对的是静态内存分配,即在程序编译时就确定了内存空间的大小和位置。
malloc函数用于在堆上分配指定大小的内存空间,其原型为:
void *malloc(size_t size);
其中,size_t为无符号整数类型,表示要分配的内存空间大小,单位是字节。函数返回值为void类型的指针,指向分配的内存空间的首地址。如果分配失败,函数返回NULL。
下面是一个简单的示例代码:
int *p = (int *)malloc(10 * sizeof(int));
if (p == NULL) {
printf("Memory allocation failed.\n");
} else {
// 使用p指针指向的内存空间
// ...
// 释放p指向的内存空间
free(p);
}
在上面的代码中,malloc函数分配了10个int类型的内存空间,大小为40字节。如果分配成功,p指针将指向这个内存空间的首地址。使用完这个内存空间后,需要使用free函数将其释放,以便其他程序可以使用。
free函数的原型为:
void free(void *ptr);
其中,ptr为指向要释放的内存空间的指针。调用free函数后,该内存空间将被释放,可以被其他程序使用。需要注意的是,如果ptr指向的内存空间已经被释放,或者ptr为NULL,调用free函数将会产生未定义的行为。
需要注意的是,动态内存分配需要谨慎使用,否则可能会导致内存泄漏、内存溢出等问题。在使用malloc和free函数时,应该遵循以下原则:
- 在使用malloc函数分配内存空间后,一定要及时使用free函数释放内存空间,避免内存泄漏。
- 在使用指向动态内存空间的指针之前,一定要检查指针是否为NULL,避免出现未定义的行为。
- 在使用malloc函数分配内存空间时,要确保分配的内存空间大小足够,避免内存溢出。
- 在使用free函数释放内存空间时,要确保要释放的内存空间确实是动态分配的,避免出现未定义的行为。
总之,malloc和free函数是C语言中非常重要的动态内存分配函数,需要谨慎使用,遵循相关的使用原则,以避免出现内存相关的问题。
动态分配线性表代码eg
#include <stdio.h>
#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 = 8;
L.MaxSize = InitSize;
}
//增加动态数组的长度
// realloc函数也可实现
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;
}
扩展
−
−
r
e
a
l
l
o
c
函数:
\color{green}扩展 -- realloc函数:
扩展−−realloc函数:
realloc函数是C语言标准库中用于重新分配内存空间的函数。其原型为:
void *realloc(void *ptr, size_t size);
其中,ptr为指向要重新分配内存空间的指针,size为要分配的新内存空间的大小,单位是字节。函数返回值为void类型的指针,指向新分配的内存空间的首地址。如果分配失败,函数返回NULL。
realloc函数在以下情况下非常有用:
- 当需要扩大已分配内存空间的大小时,可以使用realloc函数将已分配的内存空间扩大到新的大小。
- 当需要缩小已分配内存空间的大小时,可以使用realloc函数将已分配的内存空间缩小到新的大小。
- 当需要使用已分配的内存空间大小时,可以使用realloc函数获取当前已分配内存空间的大小。
下面是一个简单的示例代码:
int *p = (int *)malloc(10 * sizeof(int));
if (p == NULL) {
printf("Memory allocation failed.\n");
} else {
// 使用p指针指向的内存空间
// ...
// 扩大p指向的内存空间
int *q = (int *)realloc(p, 20 * sizeof(int));
if (q == NULL) {
printf("Memory reallocation failed.\n");
} else {
// 使用q指针指向的内存空间
// ...
// 缩小q指向的内存空间
int *r = (int *)realloc(q, 5 * sizeof(int));
if (r == NULL) {
printf("Memory reallocation failed.\n");
} else {
// 使用r指针指向的内存空间
// ...
// 获取r指向的内存空间大小
size_t size = malloc_usable_size(r);
printf("Memory size: %zu bytes.\n", size);
// 释放r指向的内存空间
free(r);
}
}
}
在上面的代码中,首先使用malloc函数分配了10个int类型的内存空间,大小为40字节。然后,使用realloc函数将这个内存空间扩大到20个int类型,大小为80字节;再使用realloc函数将这个内存空间缩小到5个int类型,大小为20字节。最后,使用malloc_usable_size函数获取当前内存空间的大小,并使用printf函数输出。使用完这个内存空间后,需要使用free函数将其释放,以便其他程序可以使用。
需要注意的是,realloc函数可能会重新分配内存空间,因此使用realloc函数时,一定要注意指针的有效性,避免出现未定义的行为。
顺序表的特点
代码实现:data[i-1];
①随机访问,即可以在O(1)时间内找到第
i
i
i 个元素。
②存储密度高,每个节点只存储数据元素
③拓展容量不方便(即便采用动态分配的方式实现,拓展长度的时间复杂度也比较高)