动态语言相对于静态语言的一个优势,就是数组可以不需要预先确定大小,对于一些数组长度不确定的场景下是非常有用的。像PHP,只需要声明一下数组 $arr = array()
然后就可以直接 $arr[] = 1,$arr[] = 2,$arr[] = 3
...这样一直加元素了,删除一个元素就直接使用unset($arr[1]),元素的空间就被释放了,而C和JAVA原生的数组就没有这么方便,声明的时候就必须先预先确定长度,由编译器分配相应的内存空间。不过通过一些巧妙的做法,也是可以实现一样的功能的,这也是本文的主要内容。
JAVA版
JAVA自带了一个集合类ArrayList,可以实现动态数组的功能,相比原生的数组,使用起来非常方便。在阅读Tomcat源码的时候,发现出于性能考虑使用了原生的数组,而没有直接使用原生的ArrayList,自己实现了一个动态数组,下面的这个实现就是直接从Tomcat的源码借鉴过来的。
实现思路
动态添加元素
初始化一个数组,大小固定。
获取源数组的大小,在方法区里面申请一个比原有数组大1位的数组。
关键的内容是,调用System.arraycopy(src, 0, dest, 0, src.length),从src的0位复制src.length位到dest的0位,这里用系统自带的方法比较方便,也可以自己写一个循环进行复制。
把要添加的元素放到新数组的最后一位。
返回元素,把新数组的指针复制到原数组变量,JAVA的数组是引用型的,执行 src=dest 后,两者实际上是指向同一个内存地址。
动态删除元素
初始化一个数组,大小固定。
在方法区申请一个比原生数组小一位的数组
从index位开始,把后面的元素同时往前移动一位,覆盖要删除的元素。
返回元素,把改变原数组的指向到新数组
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
package demo; import java.util.Arrays; public class DiyArrayListDemo { public static void main(String[] args){ int [] arr = { 5 , 8 , 10 }; System.out.println(Arrays.toString(arr)); //=>[5, 8, 10] arr = DiyArrayList.add(arr, 15 ); arr = DiyArrayList.add(arr, 20 ); arr = DiyArrayList.add(arr, 25 ); System.out.println(Arrays.toString(arr)); //=>[5, 8, 10, 15, 20, 25] arr = DiyArrayList.remove(arr, 1 ); System.out.println(Arrays.toString(arr)); //=>[5, 10, 15, 20, 25] } } class DiyArrayList{ public static int [] add( int [] src,Integer newData){ //定义目标数组,长度是比原始数组多一位 int [] dest = new int [src.length+ 1 ]; //从src的0位开始,复制到dest的0位置,复制长度是src的长度 System.arraycopy(src, 0 , dest, 0 , src.length); //填充最后一位的值 dest[src.length] = newData; return dest; } public static int [] remove( int [] src,Integer index){ //定义目标数组,长度是比原始数组少一位 int [] desc = new int [src.length- 1 ]; for ( int i= 0 ; i<src.length; i++){ //超过索引index的数据往前移动一位 if (i > index){ desc[i- 1 ] = src[i]; } else { desc[i] = src[i]; } } return desc; } } |
C语言版
C语言中实现动态数组相对比较复杂一点,因为C语言要对指针,内存进行操作。开始之前需要定义一个结构体arrayList和结构体变量ArrayList,里面包含两个数组,一个是int类型的指针,用来指向存储int型数组的内存,还有一个count,用来记录数组的长度,因为通过malloc(),realloc()进行动态内存分配(程序执行的时候分配),用sizeof()是无法获取到正确的内存长度的,所以必须要定义一个变量count去记录到底向系统申请了多少内存。为什么需要用malloc而不是像JAVA那样直接用new int[] 来创建一个数组呢?这就涉及了JAVA和C内存分配的一个区别,JAVA方法里面的数组是存放在堆中,而C函数里面的数组分配的内存是存放在栈中的,函数执行结束,数组的内存空间就会被释放,因此需要用malloc从栈申请空间。
实现思路
动态添加元素
通过realloc() 重新申请一个新的内存空间,空间比当前数组的大一个int长度,通过int*类型的指针指向该空间。
把数据放在数组的最后一位。
把记录的数组长度进行++操作。
动态删除元素
判断函数传入的index是否有效。
把大于index的数组数据往前移动一个索引。
重新申请空间,数组长度缩减一个int长度。
把记录的数组长度进行--操作。
demo.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
//定义一个结构体,data里面储存的是int类型指数组,count存储的是数组的长度 typedef struct arrayList { int * data; int count; } ArrayList; void initArrayList(ArrayList* list); void arrayListAdd(ArrayList* list, int data); void arrayListRemove(ArrayList* list, int index); void printAll(ArrayList list); demo.c #include <stdio.h> #include <stdlib.h> #include "test.h" int main() { ArrayList arrayList; initArrayList(&arrayList); arrayListAdd(&arrayList, 10 ); arrayListAdd(&arrayList, 13 ); arrayListAdd(&arrayList, 15 ); arrayListRemove(&arrayList, 2 ); printAll(arrayList); } /******************************** 函数名:initArrayList() 功能:初始化ArrayList结构体 输入:ArrayList类型结构体指针 输出:无 */ void initArrayList(ArrayList* arrayList) { arrayList->data = NULL; arrayList->count = 0 ; } /******************************* 函数名:arrayListAdd() 功能:添加数据到ArrayList类型结构体里面的数组 输入:ArrayList类型结构体指针,int类型数据 输出:无 */ void arrayListAdd(ArrayList* list, int data) { int count = list->count; //重新申请空间,空间比现在的长度大1个int长度 int * newDataArr = ( int *)realloc(list->data,sizeof( int ) * (++count)); if (newDataArr != NULL) { list->data = newDataArr; list->data[count - 1 ] = data; list->count++; } else { puts( "申请空间失败" ); } } /******************************* 函数名:arrayListRemove() 功能:根据index删除ArrayList类型结构体里面的数组元素 输入:ArrayList类型结构体指针,int类型索引 输出:无 */ void arrayListRemove(ArrayList* list, int index) { if (index > list->count) { puts( "超出数组索引" ); exit( 1 ); } //把大于index的数组数据往前移动一个索引 for ( int i = 0 ; i < list->count; i++) { if (i > index) { list->data[i - 1 ] = list->data[i]; } } int count = list->count; //重新申请空间,数组长度缩减一个int长度 int *newDataArr = realloc(list->data, sizeof( int ) * (--count)); if (newDataArr != NULL) { list->data = newDataArr; list->count = count; } else { puts( "申请空间失败" ); } } /******************************** 函数名:打印所有数组 输入:ArrayList类型结构体 */ void printAll(ArrayList list) { for ( int i = 0 ; i < list.count; i++) { printf( "%d \r\n" , list.data[i]); } } |
总结
以上所述是小编给大家介绍的Java简单使用静态语言实现动态数组,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对服务器之家网站的支持!
原文链接:http://www.cnblogs.com/jaychan/p/7691304.html?utm_source=tuicool&utm_medium=referral