我认为创建在C中运行时增长的列表的唯一方法是使用链表吗?
答案 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)
答案 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;
}
}