数据结构篇之---动态数组(二)

想起多年前刚毕业去线下面试、笔试时的一件事情。当时有个笔试就一个题目,要求用到动态数组实现某个玩意,当时我直接定义一个main函数的传参x,作为int array[x]数组的动态大小,结果编译时就报错了。哈哈,当时不知道实际上可以用 realloc 来实现动态数组的功能引起的一个小插曲。

希望该文章在某一时刻对你有所帮助。

进入正题,先说下使用realloc实现动态数组的优点:

1、高效的随机访问:动态数值支持通过下标索引随机访问,时间复杂度为O(1)。这对需要频繁访问的场景来说的十分高效的;

2、尾插高效:尾插是高效的,只要在原来的空间追加分配即可。

3、内存空间连续

缺点:

1、插入数据不灵活:没办法在中间插入(如果需要随机插入场景可以考虑使用链表)

一、代码实现

1、代码段分析

①、数据结构的定义

/* 宏定义 */
#define RET_SUCC (0)
#define RET_FAIL (-1)

/* 数据结构 */
typedef struct {
    int id;
    char name[32];
}Item, *pItem;
 
typedef struct {
    pItem        items;
    unsigned int items_nr;  // items数量
}DataModel;

/* 全局变量 */
static DataModel g_data_model;

/* ******
  数据结构说明:
  定义 Item 结构体,表示一个具体的实例,包含 id、name。
  定义 DataModel(g_data_model) 作为数据库,包含所有的实例信息。items_nr 为实例个数,items 为实例列表。
* ******* /

 ②、初始化、增、删、查函数实现

/* 函数声明 */
static void initDataModel();
static int addItem(Item *item);
static int delItem(int id);
static int freeDataModel();
static void dumpDataModel();
 
static int addItemApi(int id, char *name);


/* 局部函数 */
// 初始化函数
static void initDataModel()
{
    g_data_model.items = NULL;
    g_data_model.items_nr = 0;
}
 
// ADD: 添加一个item
static int addItem(Item *item)
{
    void *p = NULL;
 
    // realloc memory
    if(0 == g_data_model.items_nr)
    {
        p = realloc(NULL, sizeof(Item));
    }
    else
    {
        p = realloc(g_data_model.items, (g_data_model.items_nr + 1) * sizeof(Item));
    }
 
    if(NULL == p)
    {
        perror("realloc fail:");
        return RET_FAIL;
    }
 
    // copy-item-value
    g_data_model.items = p;
    g_data_model.items[g_data_model.items_nr].id = item->id;
    snprintf(g_data_model.items[g_data_model.items_nr].name, \
        sizeof(g_data_model.items[g_data_model.items_nr].name), \
        "%s", item->name);
    g_data_model.items_nr ++;
 
    return RET_SUCC;
}
 
static int addItemApi(int id, char *name)
{
    Item item = {0};
 
    item.id = id;
    snprintf(item.name, sizeof(item.name), "%s", name);
 
    return addItem(&item);
}
 
 
// DEL: 依据id删除一个item
static int delItem(int id)
{
    int i = 0;
    unsigned int old_items_nr = g_data_model.items_nr;
    void *p = NULL;
    Item *item = NULL;
    Item item_back = {0};
 
    for(i = 0; i < old_items_nr; i++)
    {
        item = &g_data_model.items[i];
        if(id != item->id)
            continue;
 
        // backup
        memcpy(&item_back, item, sizeof(item_back));
 
        // 将最后的item节点移至到要删除的节点
        item->id = g_data_model.items[old_items_nr-1].id;
        snprintf(item->name, sizeof(item->name), \
            "%s", g_data_model.items[old_items_nr-1].name);
 
        p = realloc(g_data_model.items, (old_items_nr - 1) *sizeof(Item));;
        if(1 != old_items_nr && NULL == p) {
            // restore
            memcpy(item, &item_back, sizeof(Item));
            return RET_FAIL;
        }
 
        g_data_model.items_nr--;
        return RET_SUCC;
    }
 
    // not found
    return RET_FAIL;
}
 
// FREE: 释放data model
static int freeDataModel()
{
    if(0 == g_data_model.items_nr || NULL == g_data_model.items)
        return RET_SUCC;
 
    free(g_data_model.items);
    g_data_model.items = NULL;
    g_data_model.items_nr = 0;
 
    return RET_SUCC;
}
 
// DUMP: 打印data model
static void dumpDataModel()
{
    int i = 0;
 
    if(0 == g_data_model.items_nr)
    {
        printf("data model is empty\n ");
        return ;
    }
 
    for(i = 0; i < g_data_model.items_nr; i++)
    {
        printf("\n----- items<%d> -----\n", i);
        printf("id   = %d\n", g_data_model.items[i].id);
        printf("name = %s\n", g_data_model.items[i].name);
    }
}


③、main 函数

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
 
 
// main函数
int main(void)
{
    int ret = RET_SUCC;
 
    initDataModel();
 
    // ADD
    ret += addItemApi(10, "CC1");
    ret += addItemApi(20, "CC2");
    ret += addItemApi(30, "CC3");
    ret += addItemApi(40, "CC4");
    ret += addItemApi(50, "CC5");
    if(RET_SUCC != ret)
        printf("\033[31m[warning]\033[0m ret = %d\n", ret);
    dumpDataModel();
 
 
    // DEL
    ret = RET_SUCC;
    ret += delItem(10);
    ret += delItem(30);
    ret += delItem(50);
    if(RET_SUCC != ret)
        printf("\033[31m[warning]\033[0m ret = %d\n", ret);
    dumpDataModel();
 
 
    // FREE
    ret = RET_SUCC;
    ret = freeDataModel();
    if(RET_SUCC != ret)
        printf("\033[31m[warning]\033[0m ret = %d\n", ret);
 
    return 0;
}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值