ANSI C中的动态列表?

时间:2010-10-31 16:05:19

标签: c

我认为创建在C中运行时增长的列表的唯一方法是使用链表吗?

4 个答案:

答案 0 :(得分:7)

您可以使用malloc和realloc的组合。首先初始化C数组(malloc)并增长它(realloc)。但是,如果要进行大量插入操作,则不希望一次增加1个元素。最好提出一个方案,使列表在需要时增长(即每次列表大小达到分配的大小时添加10个元素)。

答案 1 :(得分:3)

链接列表是一种方式。它有O(1)插入(假设您已经在插入点)和删除,但O(n) n元素查找。

使用malloc调整动态分配的数组的大小是另一个。它有O(1) n个元素查找但O(n)插入(由于必须复制插入点之后的所有后续元素,可能还有realloc上的所有元素)和删除

如果你真的担心这两个操作的性能,我会采用某种自平衡树结构。您可以在查找,插入和删除时获得O(log n)。对于所有实际目的,如果对象在主内存中,log n的界限为32或64,O(log n)也可能为O(1)

答案 2 :(得分:1)

查看utlistutarray。 utlist基本上是一个链表,而utarray是malloc / realloc宏。您可以轻松地将它们设置为内联函数。

答案 3 :(得分:0)

我使用可以动态增长的malloc和realloc创建了一个列表。我目前没有最新的代码,但是这里有一些(不完整的,但功能齐全的)代码,我在一段时间内用C语言管理动态,通用的列表。

#include<stdbool.h>

struct empty_list_key{
    int offest;
    struct empty_list_key* next;
};

typedef struct list_t{
    int CURRENT_POSITION; //position of the array cursor.
    int BLOCK_SIZE; //size of data type
    int SIZE;
    void** data;
    struct empty_list_key* empty_keys;
}list_t;

list_t* init_list(int size, int blocksize){
    if(size < 0){
        return NULL;
    }
    list_t *list = malloc(sizeof(list_t));
    if(list == NULL){
        return NULL;
    }
    list->CURRENT_POSITION = 0;
    list->BLOCK_SIZE = blocksize;
    list->SIZE = size;
    list->data = malloc(sizeof(void*) * size);
    if(list->data == NULL){
        free(list);
        return NULL;
    }
    if(size > 0){
        int i;
        struct empty_list_key* empty_key;
        empty_key = malloc(sizeof(struct empty_list_key));
        //TODO: Check for NULL. If NULL, cleanup everything and return.
        empty_key->offest = 0;
        if(size > 1){
            for(i = 1; i < size; i++){
                empty_key->next = malloc(sizeof(struct empty_list_key));
                //TODO: Check for NULL. If NULL, cleanup everything and return.
                empty_key = empty_key->next;
                empty_key->offest = i;
            }
        }
    }else{
        list->empty_keys = NULL;
    }
    return list;
}

void delete_list(list_t* list){
    free(list->data);
    free(list);
}

bool list_set(list_t* list, int pos, void* value){
    if(pos < list->SIZE && pos >= 0){
        list->data[pos] = value;
        return true;
    }else{
        return false;
    }
}
bool list_unset(list_t* list, int pos){
    if(pos < list->SIZE && pos >= 0){
        free(list->data[sizeof(void*) * pos]);
        list->data[pos] = NULL;
        struct empty_list_key* empty_key = malloc(sizeof(struct empty_list_key));
        if(empty_key == NULL){
            return false;
        }

        //insert empty key at beginning of empty keys linked list.
        empty_key->offest = pos;
        empty_key->next = list->empty_keys;
        list->empty_keys = empty_key;
        return true;
    }else{
        return false;
    }
}

void* list_get(list_t* list, int pos){
    if(pos < list->SIZE && pos >= 0){
        return list->data[pos];
    }else{
        return NULL;
    }
}

bool list_push(list_t* list,void* value){
    void** tmp = realloc(list->data,(sizeof(void*) * list->SIZE) + sizeof(void*));
    if(tmp == NULL){
        return false;
    }else{
        list->data = tmp;
        list->SIZE ++;
        list_set(list,list->SIZE-1,value);
        return true;
    }
}

void* list_pop(list_t* list){
    void* value = list_get(list,list->SIZE-1);
    void** tmp = realloc(list->data,(sizeof(void*) * (list->SIZE ) ));
    if(tmp == NULL){
        return NULL;
    }else{
        list->SIZE --;
        list->data = tmp;
        return value;
    }
}

int list_size(list_t* list){
    return list->SIZE;
}

bool list_add(list_t* list, void* value){
    if(list->empty_keys == NULL){
        return list_push(list,value);
    }else{
        int offset = list->empty_keys->offest;
        struct empty_list_key* empty_key = list->empty_keys->next;
        free(list->empty_keys);
        list->empty_keys = empty_key;
        return list_set(list,offset,value);
    }
}

bool list_remove(list_t* list, int pos){
    struct empty_list_key* empty_key = malloc(sizeof(struct empty_list_key));
    if(empty_key == NULL)   return false;

    if(list_unset(list,pos)){
        empty_key->offest = pos;
        empty_key->next = list->empty_keys;
        list->empty_keys = empty_key;
        return true;
    }else{
        return false;
    }
}