快速学习C语言四: 造轮子,ArrayList
高级语言里的列表是最常用的数据结构,在C里造个轮子玩玩,C没有泛型,先用int练习。
Collection的ADT一般有hasnext,next,add, remove操作,List一般还加了removeat, insert等,然后Stack有push和pop,Queue有enqueue和dequeue。列表有种实现, ArrayList和LinkedList,总体来说ArrayList更常用一些,就先用数组实现个列表。
ArrayList在末尾的添加和删除还是挺快的(O(1)),所以当栈来用挺好,Push和Pop都在末尾。 当队列的话,Enqueue在数组头部放入元素,所有右边的元素都要向右移动(O(N)),比较耗 时,不如LinkedList。另外获取指定索引数据或设置指定索引的数据是O(1)复杂度, 比LinkedList快,如果要想查看是否有指定数据,或删除指定数据,要扫描全表,复杂度 是O(N)。哦,删除指定位置的数据复杂度也是O(N), 因为删除后右边的数据要全部向 左移动。
可以开始了,首先定义一个结构来保存状态
struct arr_list {
int * arr; // 内部数组
int index; // 实际数据大小
int size; // 预分配空间大小
};
创建一个array list
struct arr_list* create_arr_list(n) {
if (n < ) {
n = ;
}
struct arr_list *arr = (struct arr_list*)malloc(sizeof(struct arr_list));
arr->arr = (int*)malloc(sizeof(int) * n);
arr->size = n;
arr->index = ;
return arr;
}
空间不足时自动扩容,默认策略是空间不够时申请双倍大小空间, 然后把原有数据拷贝到 新空间,并把原有空间释放掉, 该函数一般是新增元素前调用,所以判断条件是当实际 所用空间已经等于或大于(应该不可能)预分配空间时扩容。
static void expand_space(struct arr_list *arr) {
int *tmp, i, *p, *q;
if (arr->index >= arr->size) {
tmp = (int *)malloc(sizeof(int) * arr->size * );
p = arr->arr;
q = tmp;
for (i = ; i < arr->index; i++) {
*q++ = *p++;
}
free(arr->arr);
arr->arr = tmp;
arr->size = arr->size * ;
}
}
在指定位置插入新元素,现有元素向右移,O(N)
int list_insert(struct arr_list *arr, int index, int obj) {
int i;
if (index < || index > arr->index) {
return -;
}
expand_space(arr);
for (i = arr->index; i > index ; i--) {
arr->arr[i] = arr->arr[i - ];
}
arr->arr[index] = obj;
arr->index++;
return ;
}
在array list 末尾插入数据, O(1)
int list_push(struct arr_list *arr, int obj) {
return list_insert(arr, arr->index, obj);
}
删除指定位置的数据,O(N), 删除数据后,所有数据向左移动
int list_removeat(struct arr_list *arr, int index) {
int i;
if (index < || index >= arr->index) {
return -;
}
for (i = index; i < arr->index - ; i++) {
arr->arr[index] = arr->arr[index + ];
}
arr->index--;
return ;
}
移除并返回末尾的数据, O(1)
int list_pop(struct arr_list *arr) {
return list_removeat(arr, arr->index - );
}
判断 array list里是否包含某个数据, O(N)
int list_index(const struct arr_list *arr, int obj) {
int i;
for (i = ; i < arr->index; i++) {
if (arr->arr[i] == obj) {
return i;
}
}
return -;
}
删除某个数据项,O(N), 只删第一次出现的位置, 删除后所有数据向左移动
int list_remove(struct arr_list *arr, int obj) {
int i, index;
index = list_index(arr, obj);
if (index != -) {
for (i = index; i < arr->index - ; i++) {
arr->arr[i] = arr->arr[i + ];
}
arr->index--;
}
return index;
}
释放一个array list的内存
int free_arr_list(struct arr_list *arr){
free(arr->arr);
free(arr);
return ;
}
从头打印一个arr list
void print_arr_list(const struct arr_list *arr) {
int i, t;
printf("size=%d,index=%d\n", arr->size, arr->index);
for (i = ; i < arr->index; i++) {
list_get(arr, i, &t);
printf("list[%d]=%d\n", i, t);
}
}
最后整体测试一下
int main(void)
{
struct arr_list *arr;
int r; arr = create_arr_list();
printf("list push: 5, 6, 7\n");
list_push(arr, );
list_push(arr, );
list_push(arr, );
print_arr_list(arr); printf("list push: 8, will auto expand\n");
list_push(arr, );
print_arr_list(arr); printf("list remove at 2\n");
list_removeat(arr, );
print_arr_list(arr); printf("list pop \n");
list_pop(arr);
print_arr_list(arr); printf("list insert 0\n");
list_insert(arr, , );
print_arr_list(arr); r = list_index(arr, );
printf("list index 3:%d\n", r);
r = list_index(arr, );
printf("list index 7:%d\n", r); printf("list remove 3\n");
list_remove(arr, );
print_arr_list(arr); printf("list set index 0 = 3\n");
list_set(arr, , );
print_arr_list(arr); free_arr_list(arr);
return ;
}
小结
用C实现一下高级语言里常用的数据结构,可以对它们有更深的理解。
快速学习C语言四: 造轮子,ArrayList的更多相关文章
- 快速学习C语言一: Hello World
估计不会写C语言的同学也都听过C语言,从头开始快速学一下吧,以后肯定能用的上. 如果使用过其它类C的语言,如JAVA,C#等,学C的语法应该挺快的. 先快速学习并练习一些基本的语言要素,基本类型,表达 ...
- 快速学习C语言三: 开发环境, VIM配置, TCP基础,Linux开发基础,Socket开发基础
上次学了一些C开发相关的工具,这次再配置一下VIM,让开发过程更爽一些. 另外再学一些linux下网络开发的基础,好多人学C也是为了做网络开发. 开发环境 首先得有个Linux环境,有时候家里机器是W ...
- 快速学习C语言二: 编译自动化, 静态分析, 单元测试,coredump调试,性能剖析
上次的Hello world算是入门了,现在学习一些相关工具的使用 编译自动化 写好程序,首先要编译,就用gcc就好了,基本用法如下 gcc helloworld.c -o helloworld.o ...
- 快速学习C语言途径,让你少走弯路
1.标准C语言能干什么? 坦白讲,在今天软件已经发展了半个多世纪,单纯的C语言什么都干不了.标准C语言库只提供了一些通用的逻辑运算方法以及字符串处理,当然字符串在C语言看来也是一种操作内存的方法,所以 ...
- 造轮子ArrayList
这篇博客实现一个简单的ArrayList集合.博客里的代码首先根据自己的想法实现,在走不动的情况下会去参考JDK源代码.所以阅读本文,不要抱着跟JDK源码对比的心态.于我个人而言,国庆期间,纯属娱乐. ...
- Vue快速学习_第四节
获取原生的DOM方式($.refs) 给标签或者组件 添加ref <div ref = 'liu'>test</div> <Home ref = 'home'>&l ...
- 一起学习造轮子(一):从零开始写一个符合Promises/A+规范的promise
本文是一起学习造轮子系列的第一篇,本篇我们将从零开始写一个符合Promises/A+规范的promise,本系列文章将会选取一些前端比较经典的轮子进行源码分析,并且从零开始逐步实现,本系列将会学习Pr ...
- 如何快速高效率地学习Go语言
要想快速高效率地掌握Go语言,关键是要通过不断写代码去训练,熟能生巧.方法是没问题的,但具体的路径呢?就像开车,能不能给个导航?我希望这篇文章能起到一个导航的作用,这里提供的路径,应该对很多人都适合. ...
- c语言学习之第四章
第四章 第四章主要介绍了分支结构,循环结构的简单使用,还有其他简单的语句结束语句,比如,break,continue.还有gote语句.下面是我学习C语言第四章的一些心得和总结. 1简单的if语句 简 ...
随机推荐
- MVC 过滤器 构建会员是否登录
使用环境:在后台管理或者前台有会员中心的情况下使用 使用方式:这是一个用户中心的控制器 我给用户中心主页增加一个特性 [AccountFilter]这是一个过滤器的名字 public class Ac ...
- 将三维空间的点按照座标排序(兼谈为std::sort写compare function的注意事项)
最近碰到这样一个问题:我们从文件里读入了一组三维空间的点,其中有些点的X,Y,Z座标只存在微小的差别,远小于我们后续数据处理的精度,可以认为它们是重复的.所以我们要把这些重复的点去掉.因为数据量不大, ...
- 第三章 springboot + jedisCluster(转载)
本编博客转发自:http://www.cnblogs.com/java-zhao/p/5347703.html 如果使用的是redis2.x,在项目中使用客户端分片(Shard)机制. 如果使用的是r ...
- ASPNET 导出EXCEL表
其实网上有很多关于Excel的例子,但是不是很好,他们的代码没有很全,读的起来还很晦涩.经过这几天的摸索,终于可以完成我想要导出报表Excel的效果了.下面是我的效果图. 一.前台的页面图 GridV ...
- android开发学习笔记001a
Android 应用与开发环境 1.使用SDK版本:Android 2.3 . 2.发展和历史 创始人:Andy Rubin,Android公司被Google收购.07年11月5日1.0发布. 3.平 ...
- 建站阿里云、amh主机面版
阿里云 Nginx+tomcat7+Mencached负载均衡集群配置 http://blog.csdn.net/zht666/article/details/38515147 apache2.2.1 ...
- mvc理解篇
java是面向对象的语言. mvc是一种设计模式,就像论文排版,设置好论文的框架,字体,大小,颜色等,然后把论文内容往里填.mvc的出现让代码的层次更加的清晰,业务通过数据流实现. mvc框架的优点如 ...
- MYSQL使用mysqldump导出某个表的部分数据
命令格式如下: mysqldump -u用户名 -p密码 数据库名 表名 --where="筛选条件" > 导出文件路径 例子: 从meteo数据库的sdata表中导出sen ...
- js模块和级联
1.模块 模块模式的一般形式是:一个定义了私有变量和函数的函数,利用闭包创建可以访问私有变量和函数的特权函数,最后返回这个特权函数,或者把它们保存到一个可访问的地方.使用模块模式就可以摒弃全局变量的使 ...
- c++ 课堂作业(1)
一.题目 Create a program that asks for the radius of a circle and prints the area of that circle, using ...