在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;
}