• 数据结构与算法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
    
    ");
            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
    ", (int)i, tag->epc, tag->rssi);
        }
        printf("
    ");
    }
    
    void printIntArray(const Array(int) * array)
    {
        if (array == NULL || array->size == 0)
        {
            printf("empty int array
    
    ");
            return;
        }
    
        size_t i;
        //int *ptrInt;
        for (i = 0; i < array->size; i++)
        {
            //ptrInt = (int *)array_getItem(array, i);
            //printf("array[%d], value=%d
    ", *ptrInt);
            printf("array[%d], value = %d
    ", (int)i, arrayItem(array, int, i));
        }
        printf("
    ");
    }
    
    void test_tagArray()
    {
        printf("
    ########## Tag Array ##########
    ");
    
        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:
    ", (int)tags.size);
        printTagArray(&tags);
    
        printf("first index of rssi %d: %d
    ", tag3.rssi, (int)array_firstIndexOf(&tags, &tag3, tagCompareByRssi));
        printf("last index of rssi %d: %d
    ", tag3.rssi, (int)array_lastIndexOf(&tags, &tag3, tagCompareByRssi));
        printf("first index of epc %s: %d
    ", tag3.epc, (int)array_firstIndexOf(&tags, &tag3, tagCompareByEpc));
        printf("
    ");
    
        printf("tags after sort:
    ");
        array_sort(&tags, tagCompareByRssi); //自定义排序
        printTagArray(&tags);
    
        printf("tags after reverse:
    ");
        array_reverse(&tags);
        printTagArray(&tags);
    
        printf("tags after remove:
    ");
        array_removeAt(&tags, 0);
        array_remove(&tags, &tag4, tagCompareByEpc);
        printTagArray(&tags);
    
        printf("tags after clear:
    ");
        array_clear(&tags);
        printTagArray(&tags);
    
        array_free(&tags); //释放内存
    }
    
    void test_intArray()
    {
        printf("
    ########## int Array ##########
    ");
    
        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:
    ", (int)arr->size);
        printIntArray(arr);
    
        printf("first index of %d: %d
    ", i2, (int)array_firstIndexOf(arr, &i2, memcmp));
        printf("last index of %d: %d
    ", i2, (int)array_lastIndexOf(arr, &i2, memcmp));
        printf("first index of %d: %d
    ", i6, (int)array_firstIndexOf(arr, &i6, memcmp));
        printf("
    ");
    
        printf("inr array after sort:
    ");
        array_sortDesc(arr, memcmp);
        printIntArray(arr);
    
        printf("int array after reverse:
    ");
        array_reverse(arr);
        printIntArray(arr);
    
        printf("int array after remove:
    ");
        array_removeAt(arr, 0);
        array_remove(arr, &i4, memcmp);
        printIntArray(arr);
    
        printf("int array after clear:
    ");
        array_clear(arr);
        printIntArray(arr);
    
        array_free(arr); //释放内存
        free(arr);       //释放内存
    }
    
    int main(int argc, char **argv)
    {
        test_intArray();
        test_tagArray();
    
        return 0;  
    }
  • 相关阅读:
    后台菜单权限设计实现思路
    Laravel创建模型到指定目录
    laravel框架加载静态资源注意事项
    mysql 快速生成测试数据小技巧
    Lavaral基础实践——文件上传报错
    PHP常量详解:define和const的区别
    开发常用的工具网站
    windows下用navicat远程链接虚拟机Linux下MySQL数据库(测试可行)
    java异常处理机制思路总结
    记录一些比较容易含糊的概念
  • 原文地址:https://www.cnblogs.com/chenyuxin/p/15218250.html
Copyright © 2020-2023  润新知