静态和动态结构体命名方式和区别:
-
静态结构体:
- 在定义结构体时,直接在结构体中定义一个固定大小的数组来存储元素。
- 命名方式通常为
struct 结构体名
。 - 优点是简单,直接,适用于已知数据量大小且不会改变的情况。
- 缺点是灵活性差,因为数组大小固定,不能动态扩展或收缩。
-
动态结构体:
- 在定义结构体时,使用指针来动态分配内存空间。
- 命名方式通常为
typedef struct
后跟结构体名,然后使用typedef
关键字来简化类型名。 - 优点是灵活性高,可以根据需要动态分配和释放内存,适用于数据量大小不确定或经常变化的情况。
- 缺点是管理内存的复杂性增加,需要手动进行内存分配和释放。
这段代码实现了一个动态顺序表的基本操作,包括初始化和动态扩容:
#include <stdio.h>
#include <stdlib.h>
//顺序表的实现动态分配。开辟一个新内存
#define InitSize 10 //定义顺序表的初始长度
typedef struct
{
int *data; //指向动态分配的空间的指针
int MaxSize;//当前表的最大容量
int length;//当前表的长度
}Sqlist;
//初始化一个顺序表
void InitList(Sqlist *L){
//顺序表的长度是10,然后里面的每个储存的内存是int类型占据4B,那就是说十个这样的就要40B才够
L->data=(int*)malloc(InitSize*sizeof(int));
L->MaxSize = InitSize;
L->length = 0; //初始长度设置为0
}
//增加该顺序表的长度
void IncreateSize(Sqlist *L,int len){
//p指向原先L的data数据,保存
int *p = L->data;
//L的data区域开辟一个更大的空间出来 MaxSize+len
L->data=(int*)malloc((L->MaxSize+len)*sizeof(int));
//再把p刚刚储存的数据放回L的data区域内
for(int i=0;i<L->length;i++){
L->data[i] = p[i];//把数据复制到新的区域
}
//最大的数组长度变了
L->MaxSize =L->length + len;
//将p保存的数据清空
free(p); //释放原来p的内存空间
}
int main() {
Sqlist L;
//这里要写入的是地址值 ,所以使用*
//L是个结构体变量,因此使用 “结构体名.成员变量” 来引用变量
InitList(&L);
for(int i=0;i<L.MaxSize;i++){
L.data[i] = i;
L.length++;
printf("data[%d] = %d\n",i,L.data[i]);
}
printf("----------------------------------------\n");
IncreateSize(&L,5);
//C语言需要输出结构体的值要这样调用,而且必须前面是“% s字符串d数组”
for(int i=0; i<L.MaxSize; i++)
//L是一个结构体指针,因此使用“结构体指针名->成员变量名”来引用变量
printf("data[%d] = %d\n",i,L.data[i]);
return 0;
}
对代码的解释:
-
结构体定义:
- 使用
typedef
关键字定义了一个名为Sqlist
的结构体,该结构体包含三个成员:data
是一个指向整数的指针,用于动态分配内存空间。MaxSize
表示顺序表的最大容量。length
表示顺序表的当前长度。
- 使用
-
宏定义:
InitSize
定义了顺序表的初始长度为10。
-
函数
InitList
:- 该函数用于初始化顺序表。它动态分配一个初始长度为
InitSize
的整数数组,并将最大容量和当前长度分别设置为InitSize
和 0。
- 该函数用于初始化顺序表。它动态分配一个初始长度为
-
函数
IncreateSize
:- 该函数用于增加顺序表的长度。它首先保存原有数据,然后重新分配一个更大的内存空间,将原有数据复制到新空间,并更新最大容量。最后,释放原有内存空间。
-
main
函数:- 定义一个
Sqlist
类型的变量L
。 - 调用
InitList
函数初始化顺序表。 - 使用循环给顺序表赋值,并更新长度,同时打印每个元素的值。
- 调用
IncreateSize
函数增加顺序表的长度,并再次打印每个元素的值
- 定义一个
下面是一个基于静态顺序表的基本操作的实现。静态顺序表使用固定大小的数组来存储元素:
#include <stdio.h>
#define MaxSize 10 // 定义顺序表的最大长度
// 静态顺序表的定义
typedef struct {
int data[MaxSize]; // 固定大小的数组
int length; // 当前顺序表的长度
} SqList;
// 初始化顺序表
void InitList(SqList *L) {
L->length = 0; // 初始化长度为0
}
// 在顺序表L中第i个位置插入元素e
int ListInsert(SqList *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; // 在位置i处插入元素e
L->length++; // 顺序表长度增加
return 1; // 插入成功
}
// 获取顺序表L中第i个位置的元素
int GetElem(SqList L, int i) {
if (i < 1 || i > L.length) { // 检查位置是否合法
return 0; // 位置不合法
}
return L.data[i - 1]; // 返回位置i的元素
}
// 查找顺序表L中第一个值为e的元素的位置
int LocateElem(SqList L, int e) {
for (int i = 0; i < L.length; i++) {
if (L.data[i] == e) {
return i + 1; // 返回位置,位置从1开始计数
}
}
return 0; // 没有找到返回0
}
int main() {
SqList L;
InitList(&L); // 初始化顺序表
// 向顺序表中插入元素
for (int i = 1; i <= MaxSize; i++) {
ListInsert(&L, i, i); // 在位置i处插入元素i
}
// 打印顺序表中的元素
for (int i = 0; i < L.length; i++) {
printf("data[%d] = %d\n", i, L.data[i]);
}
// 获取并打印顺序表中的第5个元素
printf("Element at position 5: %d\n", GetElem(L, 5));
// 查找元素7的位置
int position = LocateElem(L, 7);
if (position) {
printf("Element 7 is at position: %d\n", position);
} else {
printf("Element 7 not found.\n");
}
return 0;
}
代码解释:
-
结构体定义:
SqList
结构体定义了一个静态顺序表,其中包含一个固定大小的数组data
和一个表示当前长度的变量length
。
-
初始化函数
InitList
:- 将顺序表的长度设置为0。
-
插入函数
ListInsert
:- 在顺序表的第
i
个位置插入元素e
。 - 检查插入位置是否合法以及顺序表是否已满。
- 从后往前移动元素,为新元素腾出位置。
- 插入元素并更新顺序表长度。
- 在顺序表的第
-
获取元素函数
GetElem
:- 获取顺序表中第
i
个位置的元素。 - 检查位置是否合法。
- 返回指定位置的元素。
- 获取顺序表中第
-
查找函数
LocateElem
:- 在顺序表中查找第一个值为
e
的元素的位置。 - 遍历顺序表,返回找到的元素的位置(从1开始计数)。
- 在顺序表中查找第一个值为
-
main
函数:- 初始化顺序表。
- 向顺序表中插入元素。
- 打印顺序表中的所有元素。
- 获取并打印顺序表中的特定位置的元素。
- 查找并打印特定元素的位置。