动态数组的实现 及 迭代器
今晚把之前的动态数组敲了一遍,感觉还是有点生疏啊,都忘记的差不多了,开辟一个void **data的动态数组,里面存的是void *,这样也实现了通用性,然后呢里面用到了函数指针,写了接口,用户可以自己写,比如void (*free)(void *ptr),还有迭代器,可以遍历任何东西,今晚先用迭代器遍历这个动态数组,为了方便,我全部用存成整数,简单方便。
其实,这个里面呢,还有一个好的小技巧,如何按照一定数进行扩容,比如,我给31,10,15你要给我变为32,而我给我33,56你要给我变为64,也就是变为32的整数倍。
#define MODE_SIZE 32
static int adjust_size(int size) { size += (MODE_SIZE - 1); size /= MODE_SIZE; size *= MODE_SIZE; return size; }
还有static我也说过,定义的函数只是为了在本文件使用。迭代器里面也要学会#define宏定义定义函数。
dynamic_array.h的声明
#ifndef _ARRAY_H_ #define _ARRAY_H_ //防止头文件出现重复的包含 #include "iterator.h" #define TRUE (1) #define FALSE (0) #define MODE_SIZE (32) #define ZERO (0) typedef unsigned char Boolean; typedef struct Array Array; //定义动态数组的结构体 struct Array{ void **data ; // 1.存储实体 int capacity; // 2.动态数组的申请大小 int count ; // 3.当前元素个数 //4.拷贝函数指针 void *(*copy)(void *src_value); //5.匹配函数指针 Boolean (*match)(void *value1, void *value2); //6.释放函数指针 void (*free)(void *ptr); //7.头部插入 Boolean (*push_front)(Array *array, void *value); //8.尾部插入 Boolean (*push_back)(Array *array, void *value); //9.头部删除 Boolean (*pop_front)(Array *array); //10.尾部删除 Boolean (*pop_back)(Array *array); //迭代器操作 //11.指向数组头部的位置 void *(*iter_head)(Iterator *iter, Array *array); //12.指向数组尾部的位置 void *(*iter_tail)(Iterator *iter, Array *array); //13.指向后一个元素的位置 void *(*iter_next)(Iterator *iter, Array *array); //14.指向前一个元素的位置 void *(*iter_prev)(Iterator *iter, Array *array); }; //动态数组操作接口 Array *init_array(int init_size) ; //动态数组的初始化 void destroy_array(Array **array); //动态数组的销毁 void array_clean(Array *array) ; //动态数组清空 //插入到指定下标的前边 Boolean array_prev_insert(Array *array, int index, void *value); //插入到指定下标的后边 Boolean array_next_insert(Array *array, int index, void *value); int get_array_count(Array *array) ; //得到动态数组的个数 void *get_array_index(Array *array, int index) ; //得到指定下标的元素 Boolean delete_index_value(Array *array, int index); //删除指定下标元素 Boolean delete_range_value(Array *array, int begin, int end) ; //删除指定下标范围的元素 int find_value(Array *array, void *value) ; //查找指定元素的下标 #endif
dynamic_array.h的实现
#include "dynamic_array.h" #include "tools.h" static Boolean array_push_front(Array *array, void *value); static Boolean array_push_back(Array *array, void *value); static Boolean array_pop_front(Array *array); static Boolean array_pop_back(Array *array); static void *array_iter_head(Iterator *iter, Array *array); static void *array_iter_tail(Iterator *iter, Array *array); static void *array_iter_next(Iterator *iter, Array *array); static void *array_iter_prev(Iterator *iter, Array *array); static void array_grow(Array *array, int size); static int adjust_size(int size); //头插、尾插、头删、尾删 static Boolean array_push_back(Array *array, void *value) { if(array == NULL || value == NULL){ return FALSE; } //如果数组容量不够,则进行增长 if(array->count >= array->capacity){ array_grow(array, array->count + MODE_SIZE); } array->data[array->count] = value; array->count++; return TRUE; } static Boolean array_push_front(Array *array, void *value) { return array_prev_insert(array, 0, value); } static Boolean array_pop_front(Array *array) { void *delete = NULL; int i = 0; // 计数器 if(array == NULL || array->count == ZERO){ return FALSE; } //进行删除操作 array->count--; //记录下被删除元素存储的地址,防止内存泄露 delete = array->data[0]; if(array->free != NULL){ array->free(delete); } //把后续的元素整体向前搬移 for(i = 0; i < array->count; ++i){ array->data[i] = array->data[i + 1]; } array->data[i] = NULL; } static Boolean array_pop_back(Array *array) { void *delete = NULL; if(array == NULL || array->count == ZERO){ return FALSE; } array->count--; delete = array->data[array->count]; if(array->free != NULL){ array->free(delete); } array->data[array->count] = NULL; return TRUE; } //动态数组迭代器操作 static void *array_iter_head(Iterator *iter, Array *array) { if(iter == NULL || array == NULL){ return NULL; } iter->index = 0; iter->size = array->count; if(array->data == NULL || array->count == ZERO){ iter->ptr = NULL; }else{ iter->ptr = array->data[0]; } return iter->ptr; } static void *array_iter_tail(Iterator *iter, Array *array) { if(iter == NULL || array == NULL){ return NULL; } iter->index = array->count - 1; iter->size = array->count; if(array->data == NULL || array->count == ZERO){ iter->ptr = NULL; }else{ iter->ptr = array->data[iter->index]; } return iter->ptr; } static void *array_iter_next(Iterator *iter, Array *array) { iter->index++; if(iter->index >= iter->size){ //容器已经遍历完成 iter->ptr = NULL; }else{ iter->ptr = array->data[iter->index]; } return iter->ptr; } static void *array_iter_prev(Iterator *iter, Array *array) { iter->index--; if(iter->index < 0){ iter->ptr = NULL; }else{ iter->ptr = array->data[iter->index]; } return iter->ptr; } //调整大小 static int adjust_size(int size) { size += (MODE_SIZE - 1); size /= MODE_SIZE; size *= MODE_SIZE; return size; } //动态数组增长的操作 static void array_grow(Array *array, int size) { int adjust = 0; //判断size和capacity的大小关系 if(array->capacity < size){ //对申请的大小进行调整(向上取整) adjust = adjust_size(size); array->capacity = adjust; if(array->data != NULL){ //动态数组扩展 array->data = Realloc(array->data, sizeof(void *) * adjust); }else{ //动态数组初始化 array->data = Malloc(sizeof(void *) * adjust); } } } //动态数组操作接口 Array *init_array(int init_size) //动态数组的初始化 { Array *array = (Array *)Malloc(sizeof(Array)); //对控制信息成员进行初始化 array->count = 0; //数组元素拷贝、比较、释放指针初始化为NULL array->free = NULL; array->match = NULL; array->copy = NULL; //头插、尾插、头删、尾删 array->push_front = array_push_front; array->push_back = array_push_back; array->pop_front = array_pop_front; array->pop_back = array_pop_back; //迭代器操作 array->iter_head = array_iter_head; array->iter_tail = array_iter_tail; array->iter_next = array_iter_next; array->iter_prev = array_iter_prev; array->data = NULL; array->capacity = 0; //对申请元素个数做判断 if(init_size > 0){ array_grow(array, init_size); } return array; } void destroy_array(Array **array) //动态数组的销毁 { if(array == NULL || *array == NULL){ return ; } //销毁数组元素对应的空间 array_clean(*array); //释放data free((*array)->data); //释放array free(*array); *array = NULL; } void array_clean(Array *array) //动态数组清空 { //先清除data存储的元素及其所指向的空间,再修改count delete_range_value(array, 0, array->count - 1); } //插入到指定下标的前边 Boolean array_prev_insert(Array *array, int index, void *value) { int i = 0; if(array == NULL || value == NULL || array->data == NULL || index < 0 || index >= array->count){ return FALSE; } //1.首先判断容量 if(array->count >= array->capacity){ array_grow(array, array->capacity + MODE_SIZE); } //2.index及以后的元素搬移(从后向前,防止被覆盖) for(i = array->count; i > =index; --i){ array->data[i] = array->data[i - 1]; } //3.插入到index array->data[i] = value; array->count++; return TRUE; } //插入到指定下标的后边 Boolean array_next_insert(Array *array, int index, void *value) { int i = 0; if(array == NULL || value == NULL || array->data == NULL || index < 0 || index >= array->count){ return FALSE; } //1.首先判断容量 if(array->count >= array->capacity){ array_grow(array, array->capacity + MODE_SIZE); } //2.index及以后的元素搬移(从后向前,防止被覆盖) for(i = array->count; i > index; --i){ array->data[i] = array->data[i - 1]; } //3.插入到index array->data[i] = value; array->count++; return TRUE; } int get_array_count(Array *array) //得到动态数组的个数 { if(array == NULL){ return ERROR; } return array->count; } void *get_array_index(Array *array, int index) //得到指定下标的元素 { if(array == NULL || array->count == ZERO || index < 0 || index >= array->count){ return NULL; } return array->data[index]; } Boolean delete_index_value(Array *array, int index) //删除指定下标元素 { return delete_range_value(array, index, index); } Boolean delete_range_value(Array *array, int begin, int end) //删除指定下标范围的元素 { int i = 0; int j = 0; if(array == NULL || array->count == ZERO || begin < 0 || begin > end || end >= array->count){ return FALSE; } //先做删除操作,再处理数组元素的移动 for(i = begin; i <= end; ++i){ if(array->free != NULL){ array->free(array->data[i]); } array->data[i] = NULL; } for(i = begin, j = end + 1; j < array->count; i++, j++){ array->data[i] = array->data[j]; } // 6 6 array->count -= (end - begin + 1); return TRUE; } int find_value(Array *array, void *value) //查找指定元素的下标 { int i = 0; int count = array->count; if(array == NULL || array->count == ZERO || value == NULL){ return ERROR; } if(array->match != NULL){ for(i = 0; i < count; ++i){ if(array->match(array->data[i], value)){ return i; } } }else{ for(i = 0; i < count; ++i){ if(array->data[i] == value){ return i; } } } return -1; #if 0 for(i = 0; i < array->count; ++i){ if(array->match != NULL){ if(array->match(array->data[i], value)){ return i; } }else{ if(array->data[i] == value){ return i; } } } #endif }
iterator.h 迭代器
#ifndef _ITERATOR_H_ #define _ITERATOR_H_ typedef struct Iterator{ void *ptr; //指向容器中元素的位置 int index; //迭代器在当前容器中的下标 int size; //迭代器指向的容器中有效元素的个数 }Iterator; // docker // // github // // dochub // // 虚拟化 /* * 正向迭代器 * * iterator * * container(list、array、stack、queue) * * */ #define FOREACH(iter, container) for(container->iter_head(&(iter), container); (iter).ptr; container->iter_next(&(iter), container)) #define foreach FOREACH /* * 反向迭代器 * * iterator * * container * * */ #define FOREACH_REVERSE(iter, container) for(container->iter_tail(&(iter), container); (iter).ptr; container->iter_prev(&(iter), container)) #define foreach_reverse FOREACH_REVERSE #endif
这次在tools文件中还多了一个relloc,只要在工具文件写进去就好
void *Realloc(void *ptr, size_t size) { void *result = realloc(ptr, size); if(result == NULL){ fprintf(stderr, "the memory is full! "); exit(1); } return result; }
main.c测试一下呗
#include <stdio.h> #include "dynamic_array.h" #include "iterator.h" void print_int(void *value); void print_int(void *value) { printf("%d ", *(int *)value); } int main(int argc, char **argv) { Array *array = init_array(30); //初始化动态数组 Iterator iter = {0}; int i = 0; int array1[] = {12, 23, 34, 45, 56, 67, 78, 89, 90}; int length = sizeof(array1) / sizeof(array1[0]); for(i = 0; i < length; ++i){ array->push_back(array, &array1[i]); } //正向遍历元素 printf("show array: "); foreach(iter, array){ print_int(iter.ptr); } printf(" "); //反向遍历元素 printf("show reverse array: "); foreach_reverse(iter, array){ print_int(iter.ptr); } printf(" "); destroy_array(&array); //动态数组的销毁 return 0; }
还要在写写关于迭代器的操作,下次吧。
声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。
- 上一篇: YII 显示代码执行时间
- 下一篇: Thinkphp 函数G 获取运行脚本内存和运行时间