数据结构与算法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;  
}

 

posted @ 2021-09-02 12:50  chenyuxin  阅读(66)  评论(0编辑  收藏  举报