顺序表采用动态分配时,空间在内存中表现为存储密度高,以及随机访问。
而空间可以在程序执行时,可以通过动态存储分配语句分配,不需要像静态分配那样一次性划分所有空间。而是通过 malloc 函数在内存中开辟一块新的内存,将数据元素复制到其中。
// Created by Dejavu_Yuan on 2024/2/28.
//动态分配顺序表
#include <stdio.h>
#include <stdbool.h>
#include "stdlib.h"
#define InitSize 10
typedef struct {
int *data;
int length;
int MaxSize;
} SeqList;
//初始化顺序表
void InitList(SeqList *L) {
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); //释放空间
}
//插入操作
bool ListInsert(SeqList *L, int i, int e) {
if (i < 1 || i > L->length + 1) {
return false;
}
if (L->length >= L->MaxSize) {
return false;
}
for (int j = L->length; j >= i; j--) {
L->data[j] = L->data[j - 1];
}
L->data[i - 1] = e;
L->length++;
return true;
}
//删除
bool ListDelete(SeqList *L, int i, int *e) {
if (i < 1 || i >= L->length) {
return false;
}
e = &L->data[i - 1];
for (int j = i; j < L->length; j++) {
L->data[j - 1] = L->data[j];
}
L->length--;
return true;
}
//按位查找
int GetElem(SeqList L, int i) {
return L.data[i - 1];
}
//按值查找
int LocateElem(SeqList L, int e) {
for (int i = 0; i < L.length; i++) {
if (L.data[i] == e) {
return L.data[i];
}
}
return 0;
}
int main() {
int e = -1;
SeqList L;
InitList(&L);
IncreaseSize(&L, 5);
//插入一些元素
ListInsert(&L, 1, 5);
ListInsert(&L, 2, 8);
ListInsert(&L, 3, 6);
// if (ListDelete(&L, 2, &e)) {
// printf("已删除第2个元素,删除元素值为%d\n", e);
// } else {
// printf("位序不合法\n");
// }
GetElem(L, 1);
printf("按位查找%d\n", GetElem(L, 1));
LocateElem(L, 8);
printf("按值查找%d\n", LocateElem(L, 8));
for (int i = 0; i < L.length; i++) {
printf("type %d = %d\n", i, L.data[i]);
}
return 0;
}
Q:
为什么使用 malloc 函数返回的存储空间起始地址需要将类型强制转换为与数据元素同类型的数据类型?
A:
动态分配中,如果没有进行强制类型转换,那么指针在指向地址时会因为类型不同导致访问的内存空间不同而发生错误(例如,int类型没有转换成double类型,那么在内存中访问地址时int类型指针会指向4个字节空间的内存,而这是double类型的一半)。