c语言——动态数组(线性表)
概念
线性结构是一种最简单且常用的数据结构。线性结枃的基本特点是节点之间满足线性关
系。本章讨论的动态数组、链表、栈、队列都属于线性结构。他们的共同之处,是节点中有
且只有一个开始节点和终端节点。按这种关系可以把它们的所有节点排列成一个线性序列。
但是,他们分别属于几种不同的抽象数据类型实现,它们之间的区别,主要就是操作的不同。
线性表是零个或者多个数据元素的有限序列,数据元素之间是有顺序的,数据元素个数
是有限的,数据元素的类型必须相同。
DynamicArray.h头文件
#pragma once
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#ifdef __cplusplus
extern "C"{
#endif
//1. 先把所需要的数据信息结构定义下来
struct DynamicArray
{
//数组存储元素的空间的首地址
void **addr;
//存储数据的内存中最大能够容纳多少元素
int capacity; //容量
//当前存储数据的内存中有多少个元素
int size; //大小
};
//初始化数组
struct DynamicArray *Init_DynamicArray(int capacity);
//插入元素
void Insert_DynamicArray(struct DynamicArray *arr, int pos, void *data);
//遍历
void Foreach_DynamicArray(struct DynamicArray *arr, void(*_callback)(void *));
//位置删除
void RemoveByPos_DynamicArray(struct DynamicArray *arr, int pos);
//按值删除
void RemoveByValue_DynamicArray(struct DynamicArray *arr, void *data, int(*compare)(void*, void *));
//销毁数组
void Destroy_DynamicArray(struct DynamicArray *arr);
#ifdef __cplusplus
}
#endif
DynamicArray.c
初始化数组
#include"DynamicArray.h"
//初始化数组
struct DynamicArray *Init_DynamicArray(int capacity)
{
if (capacity <= 0)
{
return NULL;
}
struct DynamicArray *arr = malloc(sizeof(struct DynamicArray));
if (NULL == arr)
{
return NULL;
}
arr->capacity = capacity;
arr->addr = malloc(sizeof(void *)*arr->capacity);//二级指针接收一级指针
arr->size = 0;
return arr;
}
插入元素
包含空判断,数组下标判断,扩容,位置移动等操作,有点难度。
//插入元素
void Insert_DynamicArray(struct DynamicArray *arr, int pos, void *data)
{
if (NULL == arr)
{
return;
}
if (NULL == data)
{
return;
}
if (pos < 0 || pos > arr->size)
{
pos = arr->size;
}
//判断空间是否足够
if (arr->size >= arr->capacity)
{
//1. 申请一块更大的内存空间
int newcapacity = arr->capacity * 2;
void **newspace = malloc(sizeof(void *)* newcapacity);
//2. 将原来空间的数据拷贝到新空间
memcpy(newspace, arr->addr, sizeof(void *)* arr->capacity);
//3. 释放原来空间的内存
free(arr->addr);
//4. 更新addr指向
arr->addr = newspace;
arr->capacity = newcapacity;
}
//移动元素,给pos位置空出位置来
for (int i = arr->size - 1; i >= pos; --i)
{
arr->addr[i + 1] = arr->addr[i];
}
//将新元素插入到pos位置
arr->addr[pos] = data;
arr->size++;
}
遍历
参考c语言函数指针和c语言_回调函数
函数指针是指向函数的指针变量。
通常我们说的指针变量是指向一个整型、字符型或数组等变量,而函数指针是指向函数。
函数指针可以像一般函数一样,用于调用函数、传递参数。
函数指针变量的声明:typedef int (*fun_ptr)(int,int); // 声明一个指向同样参数、返回值的函数指针类型
。
//遍历
void Foreach_DynamicArray(struct DynamicArray *arr, void(*_callback)(void *))
{
if (NULL == arr)
{
return;
}
if (NULL == _callback)
{
return;
}
for (int i = 0; i < arr->size; ++i)
{
_callback(arr->addr[i]);
}
}
按位置删除
位置向前移,思考,为什么这里不用free。
//位置删除
void RemoveByPos_DynamicArray(struct DynamicArray *arr, int pos)
{
if (NULL == arr)
{
return;
}
if (pos < 0 || pos > arr->size - 1)
{
return;
}
for (int i = pos; i < arr->size - 1; ++i)
{
arr->addr[i] = arr->addr[i + 1];
}
arr->size--;
}
按值删除
有点难度。
//按值删除
void RemoveByValue_DynamicArray(struct DynamicArray *arr, void *data, int(*compare)(void*, void *))
{
if (NULL == arr)
{
return;
}
if (NULL == data)
{
return;
}
if (NULL == compare)
{
return;
}
for (int i = 0; i < arr->size; ++i)
{
if (compare(arr->addr[i], data))
{
RemoveByPos_DynamicArray(arr, i);
break;
}
}
}
销毁数组
//销毁数组
void Destroy_DynamicArray(struct DynamicArray *arr)
{
if (NULL == arr)
{
return;
}
if (arr->addr != NULL)
{
free(arr->addr);
arr->addr = NULL;
}
free(arr);
arr = NULL;
}
动态数组测试
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include"DynamicArray.h"
struct Person
{
char name[64];
int age;
};
void myPrint(void *data)
{
struct Person *person = (struct Person *)data;
printf("Name:%s Age:%d\n", person->name,person->age);
}
int myCompare(void *d1,void *d2)
{
struct Person *p1 = (struct Person *)d1;
struct Person *p2 = (struct Person *)d2;
return strcmp(p1->name, p2->name) == 0 && p1->age == p2->age;
}
void test()
{
//创建动态数组
struct DynamicArray *da = Init_DynamicArray(5);
//动态数组添加元素
struct Person p1 = { "aaa", 10 };
struct Person p2 = { "bbb", 20 };
struct Person p3 = { "ccc", 30 };
struct Person p4 = { "ddd", 40 };
struct Person p5 = { "eee", 50 };
struct Person p6 = { "fff", 60 };
Insert_DynamicArray(da, 0, &p1);
Insert_DynamicArray(da, 0, &p2);
Insert_DynamicArray(da, 0, &p3);
Insert_DynamicArray(da, 1, &p4);
Insert_DynamicArray(da, 1, &p5);
printf("capacity:%d\n",da->capacity);
Insert_DynamicArray(da, 100, &p6); //3 5 4 2 1 6
printf("capacity:%d\n", da->capacity);
Foreach_DynamicArray(da, myPrint);
printf("---------------\n");
RemoveByPos_DynamicArray(da,2);//3 5 2 1 6
Foreach_DynamicArray(da, myPrint);
printf("---------------\n");
struct Person pDel = { "aaa", 10 };
RemoveByValue_DynamicArray(da, &pDel, myCompare);
//da->addr = NULL;
Foreach_DynamicArray(da, myPrint);
//销毁
Destroy_DynamicArray(da);
}
int main(){
test();
system("pause");
return EXIT_SUCCESS;
}
运行
capacity:5
capacity:10
Name:ccc Age:30
Name:eee Age:50
Name:ddd Age:40
Name:bbb Age:20
Name:aaa Age:10
Name:fff Age:60
---------------
Name:ccc Age:30
Name:eee Age:50
Name:bbb Age:20
Name:aaa Age:10
Name:fff Age:60
---------------
Name:ccc Age:30
Name:eee Age:50
Name:bbb Age:20
Name:fff Age:60