使用C模拟Java中的ArrayList

来源:互联网 发布:js改变input的宽度 编辑:程序博客网 时间:2024/05/22 09:04

在Java的集合类中有许多的数据结构模型,它们也称为容器。比如ArrayList、 LinkedList、TreeSet、HashMap等等。虽然这些Java类都是使用Java语言实现的,但是别忘了,其实Java也是在C/C++的基础上发展起来的,只是当初规避了C的指针的复杂和一些C++的比较繁杂的特性(虽然现在Java越来越复杂了$_$……)。

ArrayList和数组最大的区别就是ArrayList其长度是可变的,在程序的运行中不断地根据需求而增加。然而数组却不具有这样的特性,因为数组需要指定长度,且该长度在整个该数组使用的生命周期中长度是不可变的。那么如何通过C来实现ArrayList的可变长度的特性呢?在C语言中一个库函数,malloc函数,用于动态分配内存并返回指向该内存块的首地址的指针(具体关于malloc的使用请自行查阅资料)。为了长度可变我们需要操作多个变量,那么使用结构体来操作从而使得元素整体化。关于代码中的value的值类型务必要与指针的类型一致。下面直接上代码了。

#include<stdio.h>#include<stdlib.h>//实现类似于Java中的ArrayList的大部分功能struct Arr  {int *pBase; //存储的是数组第一个元素的地址int len;   //表示数组所能容纳的最大元素的个数int cnt;   //表示当前数组有效元素的个数//int increment; //自动增长因子,此处为简单起见不加实现,可以自行实现};void init_arr(struct Arr *pArr, int length);   //初始化数组bool append_arr(struct Arr *pArr, int value); //追加(在末尾处)bool insert_arr(struct Arr *pArr, int position, int value); //插入bool delete_arr(struct Arr *pArr, int position, int * pValue);  //删除bool get_arr();  //获取(此方法不予实现)bool isEmpty(struct Arr *);  //数组判空bool isFull(struct Arr *);    //是否空间已满void sort_arr(struct Arr *pArr);   //冒泡,数组排序void show_arr(struct Arr *);    //显示void inversion_arr(struct Arr *pArr); //翻转,倒置void init_arr(struct Arr *pArr, int length){pArr->pBase = (int *)malloc(sizeof(int)*length);if(pArr->pBase == NULL){printf("动态内存分配失败!\n");exit(-1); //终止整个程序}else{pArr->len=length;pArr->cnt=0;}}bool append_arr(struct Arr *pArr, int value){//数组已满时返回falseif(isFull(pArr)){return false;}else{   //不满时则追加pArr->pBase[pArr->cnt] = value;(pArr->cnt)++;/*int i=pArr->cnt;  // 对未填满的其余数组中的值赋值为-1for(i; i<pArr->len; i++){pArr->pBase[i] = -1;}*/}return true;}bool insert_arr(struct Arr *pArr, int position, int value) //position从1开始{//数组已满时返回falseif(isFull(pArr) || position<1 || position>(pArr->cnt+1)){   //插入的值应该在有效值中间或者最后一个有效值的后边return false;}else{   //不满时则插入int i;for(i=pArr->cnt-1; i>=position-1; i--){pArr->pBase[i+1] = pArr->pBase[i]; //元素向后移动一位}pArr->pBase[position-1] = value;   //position对应的数组下标应该是 position-1(pArr->cnt)++;  //插入成功后,实际有效值个数+1}return true;}bool delete_arr(struct Arr *pArr, int position, int * pDeleteValue) // int * pDeleteValue 是为了在函数执行后可在主调函数中查看被删除的值{if(isEmpty(pArr) || position<1 || position>pArr->cnt){return false;}else{   //数组中删除某个位置(position对应的数组下标就是position-1)的元素,实际上就是将该位置后的所有元素向前移动一位int i;*pDeleteValue = pArr->pBase[position-1];for(i=position; i<=pArr->cnt; i++){pArr->pBase[i-1] = pArr->pBase[i];}(pArr->cnt)--; //删除后实际长度减1}return true;}bool isEmpty(struct Arr *pArr){if(pArr->cnt==0){return true;}else{return false;}}bool isFull(struct Arr *pArr){if(pArr->cnt == pArr->len){return true;}else{return false;}}void sort_arr(struct Arr *pArr)   //冒泡,数组排序.可另行实现其它排序方法(快速排序、归并...){if(isEmpty(pArr)){printf("数组为空/长度为1,无法/无需排序!\n");return;}else{int i, j, temp;for(i=0; i<pArr->cnt; i++){for(j=i+1; j<pArr->cnt; j++){if(pArr->pBase[i] > pArr->pBase[j]){temp = pArr->pBase[i];pArr->pBase[i] = pArr->pBase[j];pArr->pBase[j] = temp;}}}}}void show_arr(struct Arr *pArr){if(isEmpty(pArr)){printf("数组内容为空!");}else{int i;for(i=0; i<pArr->len; i++){printf("%d ", pArr->pBase[i]);  // int *}printf("\n");}}void inversion_arr(struct Arr *pArr){if(isEmpty(pArr)){printf("数组为空/长度为1,无法/无需反转!\n");return;}else{int i=0, j=pArr->cnt-1;int temp;for(i=0; i<j; i++,j--){temp = pArr->pBase[i];pArr->pBase[i] = pArr->pBase[j];pArr->pBase[j] = temp;}}}//Test blockint main(void){struct Arr arr;int deleteValue=0;init_arr(&arr, 7);//printf("%d\n", arr.len);append_arr(&arr, 123);append_arr(&arr, 119);append_arr(&arr, 98);append_arr(&arr, 97);append_arr(&arr, 197);printf("使用append_arr方法添加完数据后的数据内容为:\n");show_arr(&arr);//插入数据,查看插入成功与否printf("使用insert_arr方法的插入情况(0:失败,1:成功):");printf("%d\n", insert_arr(&arr, 2, 77));printf("使用insert_arr方法插入数据后的数据内容为:\n");show_arr(&arr);//删除数据,查看删除与否和被删除的值(指针在通过被调函数修改主调函数中的参数值中的应用)printf("删除情况(0:失败,1:成功):%d\n", delete_arr(&arr, 4, &deleteValue));printf("删除的值为:%d\n", deleteValue);printf("删除后结果为:");show_arr(&arr);//反转数组inversion_arr(&arr);printf("反转数组后结果为:");show_arr(&arr);//数组冒泡排序sort_arr(&arr);printf("数组冒泡排序后结果为:");show_arr(&arr);return 0;}


关于可变长度参数increment,为了代码的简洁易读性作了删除,如果你看明白了这些代码,那么添加这个参数将是一件很容易的事,也只有在添加increment后才是一个完整的ArrayList的C语言再现。

0 0
原创粉丝点击