数据结构与算法8 — 动态数组
尊重作者劳动成果,转载请注明出处,谢谢!
1. array.h
#ifndef array_H #define array_H #include <stddef.h> #include <sys/types.h> #include "delegate.h" //动态数组,能够动态的进行扩容,支持多种数据类型,包括:int、struct等 typedef struct { void *data; //实际数组 size_t itemSize; //数组元素大小(字节) size_t capacity; //数组容量 size_t size; //数组长度 } Array;//定义该宏可以直观的看出数组元素的数据类型,比如:Array(int) #define Array(type) Array //获取指向数组第一个元素的指针 #define arrayData(array, type) \ (type *)((array)->data) //获取指定索引的数组元素 #define arrayItem(array, type, index) \ (arrayData(array, type))[index] //获取指定索引的数组元素的指针 #define arrayItemPtr(array, type, index) \ (arrayData(array, type) + index) #ifdef __cplusplus extern "C" { #endif int array_init(Array *array, size_t itemSize, size_t capacity); void array_free(Array *array); void array_clear(Array *array); int array_expand(Array *array, size_t increment); int array_shrink(Array *array); size_t array_length(const Array *array); int array_full(const Array *array); void *array_getItem(const Array *array, size_t index); void array_setItem(Array *array, size_t index, const void *item); void array_add(Array *array, const void *item); void array_insert(Array *array, const void *item, size_t index); void array_remove(Array *array, const void *item, Comparison comparison); void array_removeAll(Array *array, const void *item, Comparison comparison); void array_removeAt(Array *array, size_t index); void array_removeRange(Array *array, size_t fromIndex, size_t toIndex); ssize_t array_firstIndexOf(const Array *array, const void *item, Comparison comparison); ssize_t array_lastIndexOf(const Array *array, const void *item, Comparison comparison); int array_contains(const Array *array, const void *item, Comparison comparison); void array_sort(Array *array, Comparison comparison); void array_sortDesc(Array *array, Comparison comparison); int array_compare(const Array *arr1, const Array *arr2, Comparison comparison); void array_copy(Array *dest, const Array *src); void array_merge(Array *dest, const Array *src); void array_reverse(Array *array); #ifdef __cplusplus } #endif #endif
2. array.c
#include "array.h" #include <string.h> #include <stdlib.h> //初始化 int array_init(Array *array, size_t itemSize, size_t capacity) { if (array == NULL || itemSize <= 0) return -1; array->data = malloc(capacity * itemSize); if (array->data == NULL) return -1; memset(array->data, 0, capacity * itemSize); array->capacity = capacity; array->size = 0; array->itemSize = itemSize; return 0; } //释放内存 void array_free(Array *array) { if (array == NULL) return; if (array->data != NULL) { free(array->data); array->data = NULL; } array->size = 0; array->capacity = 0; array->itemSize = 0; } //清空数组 void array_clear(Array *array) { if (array == NULL) return; if (array->data != NULL) memset(array->data, 0, array->capacity * array->itemSize); array->size = 0; array_shrink(array); //收缩数组 } //扩充数组 int array_expand(Array *array, size_t increment) { if (array == NULL || increment <= 0) return -1; void *data = realloc(array->data, (increment + array->capacity) * array->itemSize); if (data == NULL) return -1; array->data = data; array->capacity += increment; return 0; } //收缩数组 int array_shrink(Array *array) { if (array == NULL) return -1; if (array_full(array)) return -1; size_t capacity; if (array->size == 0) capacity = 1; else capacity = array->size; void *data = realloc(array->data, capacity * array->itemSize); if (data == NULL) return -1; array->data = data; array->capacity = capacity; return 0; } //获取数组长度 size_t array_length(const Array *array) { if (array == NULL || array->data == NULL) return 0; return array->size; } //判断数据是否已满 int array_full(const Array *array) { if (array == NULL) return -1; return array->size == array->capacity; } //获取指定索引的元素,类似数组的下标访问 void *array_getItem(const Array *array, size_t index) { if (array == NULL || index >= array->size) return NULL; return (char *)array->data + index * array->itemSize; } //修改指定索引位置的元素 void array_setItem(Array *array, size_t index, const void *item) { if (array == NULL || index >= array->size) return; memcpy((char *)array->data + index * array->itemSize, item, array->itemSize); } //在数组末尾添加元素 void array_add(Array *array, const void *item) { if (array == NULL) return; if (array_full(array)) array_expand(array, array->capacity / 2); memcpy((char *)array->data + array->size * array->itemSize, item, array->itemSize); array->size++; } //在指定索引的位置上插入元素 void array_insert(Array *array, const void *item, size_t index) { if (array == NULL || index > array->size) return; if (array_full(array)) array_expand(array, array->capacity / 2); if (index >= array->size) //add { memcpy((char *)array->data + array->size * array->itemSize, item, array->itemSize); } else //insert { void *src = (char *)array->data + index * array->itemSize; void *dest = (char *)src + array->itemSize; memmove(dest, src, (array->size - index) * array->itemSize); memcpy(src, item, array->itemSize); } array->size++; } //删除满足指定条件的第一个元素 void array_remove(Array *array, const void *item, Comparison comparison) { if (array == NULL) return; size_t i; for (i = 0; i < array->size; i++) { if (comparison((char *)array->data + i * array->itemSize, item, array->itemSize) == 0) { if (i != array->size - 1) //不是最后一个元素 { void *src = (char *)array->data + (i + 1) * array->itemSize; void *dest = (char *)array->data + i * array->itemSize; memmove(dest, src, (array->size - i) * array->itemSize); } //最后一个元素,赋值为0 array->size -= 1; memset((char *)array->data + array->size * array->itemSize, 0, array->itemSize); break; } } } //删除所有满足指定条件的元素 void array_removeAll(Array *array, const void *item, Comparison comparison) { if (array == NULL) return; size_t i; for (i = 0; i < array->size; i++) { if (comparison((char *)array->data + i * array->itemSize, item, array->itemSize) == 0) { if (i != array->size - 1) //不是最后一个元素 { void *src = (char *)array->data + (i + 1) * array->itemSize; void *dest = (char *)array->data + i * array->itemSize; memmove(dest, src, (array->size - i) * array->itemSize); } //最后一个元素,赋值为0 array->size -= 1; memset((char *)array->data + array->size * array->itemSize, 0, array->itemSize); i--; //勿漏 } } } //删除指定索引位置的元素 void array_removeAt(Array *array, size_t index) { array_removeRange(array, index, index); } //删除指定索引范围的元素 void array_removeRange(Array *array, size_t fromIndex, size_t toIndex) { if (array == NULL) return; if (fromIndex > toIndex) return; if (fromIndex >= array->size || toIndex >= array->size) return; size_t num = toIndex - fromIndex + 1; size_t endIndex = array->size - 1; if (toIndex != endIndex) { void *src = (char *)array->data + (toIndex + 1) * array->itemSize; void *dest = (char *)array->data + fromIndex * array->itemSize; memmove(dest, src, (endIndex - toIndex) * array->itemSize); } array->size -= num; memset((char *)array->data + array->size * array->itemSize, 0, num * array->itemSize); } //获取满足指定条件的第一个索引,不存在时返回-1 ssize_t array_firstIndexOf(const Array *array, const void *item, Comparison comparison) { if (array == NULL) return -1; size_t i; for (i = 0; i < array->size; i++) { if (comparison((char *)array->data + i * array->itemSize, item, array->itemSize) == 0) return i; } return -1; } //获取满足指定条件的最后一个索引,不存在时返回-1 ssize_t array_lastIndexOf(const Array *array, const void *item, Comparison comparison) { if (array == NULL) return -1; ssize_t i; for (i = array->size - 1; i >= 0; i--) { if (comparison((char *)array->data + i * array->itemSize, item, array->itemSize) == 0) return i; } return -1; } //判读数组是否包含指定元素,存在返回大于0,不存在返回-1 int array_contains(const Array *array, const void *item, Comparison comparison) { return array_firstIndexOf(array, item, comparison); } //数组升序排序(直接插入排序法,使用自定义比较器) void array_sort(Array *array, Comparison comparison) { if (array == NULL || array->size == 0) return; void *tmp = malloc(array->itemSize); size_t i; ssize_t j; for (i = 1; i < array->size; i++) //默认第一个元素有序,需n-1次插入 { if (comparison((char *)array->data + i * array->itemSize, (char *)array->data + (i - 1) * array->itemSize, array->itemSize) < 0) { memcpy(tmp, (char *)array->data + i * array->itemSize, array->itemSize); j = i - 1; //查找插入位置 while (j >= 0 && comparison((char *)array->data + j * array->itemSize, tmp, array->itemSize) > 0) { //元素后移 //memcpy((char *)array->data + (j + 1) * array->itemSize, (char *)array->data + j * array->itemSize, array->itemSize); j--; } //元素后移 void *src = (char *)array->data + (j + 1) * array->itemSize; void *dest = (char *)src + 1 * array->itemSize; memmove(dest, src, array->itemSize * (i - j - 1)); //插入元素 memcpy((char *)array->data + (j + 1) * array->itemSize, tmp, array->itemSize); } } free(tmp); } //数组降序排序(直接插入排序法,使用自定义比较器) void array_sortDesc(Array *array, Comparison comparison) { if (array == NULL || array->size == 0) return; void *tmp = malloc(array->itemSize); size_t i; ssize_t j; for (i = 1; i < array->size; i++) //默认第一个元素有序,需n-1次插入 { if (comparison((char *)array->data + i * array->itemSize, (char *)array->data + (i - 1) * array->itemSize, array->itemSize) > 0) { memcpy(tmp, (char *)array->data + i * array->itemSize, array->itemSize); j = i - 1; //查找插入位置 while (j >= 0 && comparison((char *)array->data + j * array->itemSize, tmp, array->itemSize) < 0) { //元素后移 //memcpy((char *)array->data + (j + 1) * array->itemSize, (char *)array->data + j * array->itemSize, array->itemSize); j--; } //元素后移 void *src = (char *)array->data + (j + 1) * array->itemSize; void *dest = (char *)src + 1 * array->itemSize; memmove(dest, src, array->itemSize * (i - j - 1)); //插入元素 memcpy((char *)array->data + (j + 1) * array->itemSize, tmp, array->itemSize); } } free(tmp); } //数组比较(使用自定义比较器),相同返回0,大于返回大于0,小于返回小于0 int array_compare(const Array *arr1, const Array *arr2, Comparison comparison) { if (arr1 == arr2) return 0; if (arr1 == NULL || arr2 == NULL) return -1; if (arr1->size != arr2->size) return -1; int res; size_t i; for (i = 0; i < arr1->size; i++) { res = comparison((char *)arr1->data + i * arr1->itemSize, (char *)arr2->data + i * arr2->itemSize, arr1->itemSize); if (res != 0) break; } return res; } //复制数组 void array_copy(Array *dest, const Array *src) { if (dest == NULL || src == NULL) return; //src的大小比dest的容量还要大,需要扩容 if (src->size > dest->capacity) array_expand(dest, src->size - dest->capacity); memcpy(dest->data, src->data, src->size * src->itemSize); dest->size = src->size; } //数组合并 void array_merge(Array *dest, const Array *src) { if (dest == NULL || src == NULL) return; if (dest->size + src->size > dest->capacity) array_expand(dest, (dest->size + src->size - dest->capacity) * 2); memcpy((char *)dest->data + dest->size * dest->itemSize, src->data, src->size * src->itemSize); dest->size += src->size; } //数组反转 void array_reverse(Array *array) { if (array == NULL || array->size <= 1) return; void *tmp = malloc(array->itemSize); size_t i; for (i = 0; i < array->size / 2; i++) { memcpy(tmp, (char *)array->data + i * array->itemSize, array->itemSize); memcpy((char *)array->data + i * array->itemSize, (char *)array->data + (array->size - i - 1) * array->itemSize, array->itemSize); memcpy((char *)array->data + (array->size - i - 1) * array->itemSize, tmp, array->itemSize); } free(tmp); }
3. main.c
#include "array.h" #include <stdio.h> #include <string.h> #include <stdlib.h> typedef struct tag { char epc[24]; unsigned short rssi; unsigned short antennaId; } Tag; int tagCompareByRssi(const void *s1, const void *s2, size_t n) { Tag *t1 = (Tag *)s1; Tag *t2 = (Tag *)s2; if (t1->rssi == t2->rssi) return 0; else if (t1->rssi > t2->rssi) return 1; else return -1; } int tagCompareByEpc(const void *s1, const void *s2, size_t n) { Tag *t1 = (Tag *)s1; Tag *t2 = (Tag *)s2; return strcmp(t1->epc, t2->epc); } void printTagArray(const Array(Tag) * tags) { if (tags == NULL || tags->size == 0) { printf("empty tags\n\n"); return; } size_t i; Tag *tag; for (i = 0; i < tags->size; i++) { tag = (Tag *)array_getItem(tags, i); printf("tags[%d], epc = %s, rssi = %d\n", (int)i, tag->epc, tag->rssi); } printf("\n"); } void printIntArray(const Array(int) * array) { if (array == NULL || array->size == 0) { printf("empty int array\n\n"); return; } size_t i; //int *ptrInt; for (i = 0; i < array->size; i++) { //ptrInt = (int *)array_getItem(array, i); //printf("array[%d], value=%d\n", *ptrInt); printf("array[%d], value = %d\n", (int)i, arrayItem(array, int, i)); } printf("\n"); } void test_tagArray() { printf("\n########## Tag Array ##########\n"); Array(Tag) tags; array_init(&tags, sizeof(Tag), 100); Tag tag1; strcpy(tag1.epc, "11111111"); tag1.antennaId = 1; tag1.rssi = 70; array_add(&tags, &tag1); Tag tag2; strcpy(tag2.epc, "22222222"); tag2.antennaId = 2; tag2.rssi = 90; array_insert(&tags, &tag2, 0); Tag tag3; strcpy(tag3.epc, "33333333"); tag3.antennaId = 1; tag3.rssi = 80; array_add(&tags, &tag3); Tag tag4; strcpy(tag4.epc, "44444444"); tag4.antennaId = 3; tag4.rssi = 80; array_insert(&tags, &tag4, 2); Tag tag5; strcpy(tag5.epc, "55555555"); tag5.antennaId = 1; tag5.rssi = 85; array_insert(&tags, &tag5, 0); printf("tags, size: %d:\n", (int)tags.size); printTagArray(&tags); printf("first index of rssi %d: %d\n", tag3.rssi, (int)array_firstIndexOf(&tags, &tag3, tagCompareByRssi)); printf("last index of rssi %d: %d\n", tag3.rssi, (int)array_lastIndexOf(&tags, &tag3, tagCompareByRssi)); printf("first index of epc %s: %d\n", tag3.epc, (int)array_firstIndexOf(&tags, &tag3, tagCompareByEpc)); printf("\n"); printf("tags after sort:\n"); array_sort(&tags, tagCompareByRssi); //自定义排序 printTagArray(&tags); printf("tags after reverse:\n"); array_reverse(&tags); printTagArray(&tags); printf("tags after remove:\n"); array_removeAt(&tags, 0); array_remove(&tags, &tag4, tagCompareByEpc); printTagArray(&tags); printf("tags after clear:\n"); array_clear(&tags); printTagArray(&tags); array_free(&tags); //释放内存 } void test_intArray() { printf("\n########## int Array ##########\n"); Array(int) *arr = (Array(int) *)malloc(sizeof(Array)); //动态分配 array_init(arr, sizeof(int), 2); int i1 = 20; int i2 = 30; int i3 = 10; int i4 = 40; int i5 = 30; int i6 = 50; array_add(arr, &i1); array_add(arr, &i2); array_add(arr, &i3); array_insert(arr, &i4, 0); array_insert(arr, &i5, 1); array_insert(arr, &i6, arr->size); printf("int array, size: %d:\n", (int)arr->size); printIntArray(arr); printf("first index of %d: %d\n", i2, (int)array_firstIndexOf(arr, &i2, memcmp)); printf("last index of %d: %d\n", i2, (int)array_lastIndexOf(arr, &i2, memcmp)); printf("first index of %d: %d\n", i6, (int)array_firstIndexOf(arr, &i6, memcmp)); printf("\n"); printf("inr array after sort:\n"); array_sortDesc(arr, memcmp); printIntArray(arr); printf("int array after reverse:\n"); array_reverse(arr); printIntArray(arr); printf("int array after remove:\n"); array_removeAt(arr, 0); array_remove(arr, &i4, memcmp); printIntArray(arr); printf("int array after clear:\n"); array_clear(arr); printIntArray(arr); array_free(arr); //释放内存 free(arr); //释放内存 } int main(int argc, char **argv) { test_intArray(); test_tagArray(); return 0; }