使用C模拟Java中的ArrayList

在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)
{
	//数组已满时返回false
	if(isFull(pArr)){
		return false;
	}else{   //不满时则追加
		pArr->pBase[pArr->cnt] = value;
		(pArr->cnt)++;
		/*
		int i=pArr->cnt;  // 对未填满的其余数组中的值赋值为-1
		for(i; i<pArr->len; i++){
			pArr->pBase[i] = -1;
		}
		*/
	}
	return true;
}

bool insert_arr(struct Arr *pArr, int position, int value) //position从1开始
{
	//数组已满时返回false
	if(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 block
int 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值