数据结构
数组扩容–如何对一个数组进行有效的扩容
- 静态空间管理:开辟内部数组并适用一段地址连续的物理空间,capacity为总容量,size为当前的实际规模。若采用静态空间策略管理,容量capacity固定,则存在明显的不足。
上溢:capacity空间不够,不足以存放所有元素
下溢:capcity空间过大,存放的元素寥寥无几,装填因子(load factor) u=size/capacity << 50%
而在一般的环境种无法预测空间的需求量,因此需要进行动态的扩容
<pre>
public class LinearRecur {
public static void main(String[] args) {
int[] b = {0,6,5,1,9,10};
int[] a = {1,2,5,6,7,9,10};
}
public static int[] copyFrom(int[] array, int low, int high) {
int[] newArray = new int[2*(high-low)];
int size = 0;
while(low < high) {
newArray[size++] = array[low++];
}
return newArray;
}
}
</pre>
2.动态空间管理的思想:在即将发生上溢时,适当的扩大内部数组的容量。主要有两种扩容策略:
a. 第一种为容量递增策略:即每次在即将上溢时,给系统增加固定的容量。
b. 第二种为容量加倍策略:即在每次即将上溢时,在系统容量的基础上容量加倍。
两种增容算法的性能如下图所示:
无序向量
- 元素访问
- 元素插入: 由于我们这里采用的是用数组进行元素插入,因此在插入之前我们需要先对数组进行扩容,再插入
<pre>
public class LinearRecur {
public static void main(String[] args) {
int[] b = {0,6,5,1,9,10};
int[] newArray;
newArray = insert(b, 1, 100);
for (int j = 0; j < newArray.length; j++) {
System.out.println(newArray[j]);
}
}
public static int[] insert(int[] array, int rank, int num) {
int[] newArray;
newArray = copyFrom(array,0,array.length);
for (int i = array.length-1; i >= rank; i--) {
newArray[i+1] = newArray[i];
}
newArray[rank] = num;
return newArray;
}
public static int[] copyFrom(int[] array, int low, int high) {
int[] newArray = new int[2*(high-low)];
int size = 0;
while(low < high) {
newArray[size++] = array[low++];
}
return newArray;
}
}
</pre>
3.区间删除: 删除[low,high)中的元素
<pre>
public class LinearRecur {
public static void main(String[] args) { //0<=low<=high<=size
int[] b = {0,6,5,1,9,10};
int[] newArray;
newArray = delete(b, 1, 3);
for (int j = 0; j < newArray.length; j++) {
System.out.println(newArray[j]);
}
}
public static int[] delete(int[] array, int low, int high) { //0<=low<=high<=size
if(low == high) {
return array; //单独处理退化的情况
}
while(high < array.length) {
array[low++] = array[high++];
}
while(low < array.length) { //为了清除后面的内容
array[low++] = 0;
}
return array;
}
}
</pre>
4.删除:单元素删除操作:
可以通过调用区间删除操作来实现:remove = delete[rank,rank+1),删除的区间只包含一个元素
但是区间删除,不能够调用单个删除来实现,因为这样会导致时间复杂度变为O(n^2)
5.查找:查找某一指定元素
<pre>
public class LinearRecur {
public static void main(String[] args) {
int[] b = {0,6,5,1,9,10};
int index = 0;
index = find(b,0,3,5);
System.out.println(index);
}
public static int find(int[] array, int low, int high, int num) { //从[low,high)中查找num
while(high-- > low) {
if(array[high] == num) {
break;
}
}
return high;
}
}
</pre>
6.唯一化:删除数组中的重复元素
<pre>
public class LinearRecur {
public static void main(String[] args) {
int[] b = {2,6,6,6,2,9,10};
int[] array;
array = unique(b);
for (int i = 0; i < array.length; i++) {
System.out.printf("%d", array[i]);
}
}
public static int[] unique(int[] array) {
int index = 0;
int[] newArray;
int i = 1;
while(i < array.length){
index = find(array,0,i,array[i]);
if (index != -1) {
array = delete(array, index,index+1);
}else if(array[i] == 0){ //为了防止0的出现导致死循环
break;
}else {
i++;
}
}
return array;
}
public static int find(int[] array, int low, int high, int num) { //从[low,high)中查找num
while(high-- > low) {
if(array[high] == num) {
break;
}
}
return high;
}
public static int[] delete(int[] array, int low, int high) { //0<=low<=high<=size
if(low == high) {
return array; //单独处理退化的情况
}
while(high < array.length) {
array[low++] = array[high++];
}
while(low < array.length) { //为了清除后面的内容
array[low++] = 0;
}
return array;
}
}
e(high < array.length) {
array[low++] = array[high++];
}
while(low < array.length) { //为了清除后面的内容
array[low++] = 0;
}
return array;
}
}
</pre>
有序性及其甄别
有序/无序序列中,任意。/总有一对相邻元素顺序/逆序
相较于无序数组的唯一化,有序数组的唯一化可以有更加简单的实现形式。之前唯一化算法的低效在于对于同一元素作为被删除元素的后继需要进行多次前移,这就导致无序数组的唯一化具有低效的性能。而有序数组若能以区间为单位,删除重复元素势必将大大提高算法的性能,同时有序数组无需向前查找,这也是算法提高性能的一个方面。下面是有序数组唯一化的实现过程。
<pre>
public class LinearRecur {
public static void main(String[] args) {
int[] b = {2,6,6,9,10,10};
int[] array;
array = unique(b);
for (int i = 0; i < array.length; i++) {
System.out.printf("%d", array[i]);
}
}
public static int[] unique(int[] array) {
int index1=0;
int index2 =0;
while(++index2 < array.length) {
if(array[index2] != array[index1]){
array = delete(array, index1+1, index2);
index1 += 1;
index2 = index1;
}
if(array[index2] == 0) {
break;
}
}
return array;
}
public static int[] delete(int[] array, int low, int high) { //0<=low<=high<=size
if(low == high) {
return array; //单独处理退化的情况
}
while(high < array.length) {
array[low++] = array[high++];
}
while(low < array.length) { //为了清除后面的内容
array[low++] = 0;
}
return array;
}
}
</pre>