1.青铜挑战
1.1线性表
线性表就具有相同特征数据元素的一个有限序列,其中所含元素的个数称为线性表的长度,从不同角度,线性表有不同分类
语言角度:
图a为一体式结构,存储表信息的单元与元素存储区以连续的方式安排在一块存储区里,两部分数据的整体形成一个完整的顺序表对象,例如c和cpp
图b为分离式结构,表对象里只保存与整个表有关的信息(即容量和元素个数),实际数据元素存放在另一个独立的元素存储区里,通过链接与基本表对象关联,例如java和python
存储角度:
顺序型和链表型
从访问限制的角度:
栈和队列访问受限,只能在固定位置进行操作
从扩容的角度:
采用分离式结构的顺序表,若将数据区更换为存储空间更大的区域,则可以在不改变表对象的前提下对其数据存储区进行了扩充,所有使用这个表的地方都不必修改。只要程序的运行环境(计算机系统)还有空闲存储,这种表结构就不会因为满了而导致操作无法进行。人们把采用这种技术实现的顺序表称为动态顺序表,因为其容量可以在使用中动态变化。
扩充的两种策略:
第一种:每次扩充增加固定数目的存储位置,如每次扩充增加10个元素位置,这种策略可称为线性增长。特点:节省空间,但是扩充操作频繁,操作次数多。
第二种:每次扩充容量加倍,如每次扩充增加一倍存储空间。特点:减少了扩充操作的执行次数,但可能会浪费空间资源。以空间换时间,推荐的方式。
1.2数组的插入和删除
数组的插入和删除操作重点在于插入或删除结点位置的确定,结点的移动,以及一些边界位置的判断
代码如下
插入操作
/**
*
* @param arr 进行插入操作的数组
* @param size 数组已存储元素的个数
* @param key 插入的数
* @return
*/
//该插入操作的前提是数组是非递减
public static int insert(int[] arr,int size,int key){
//数组已满无法插入
if(size==arr.length){
return 0;
}
//初始插入位置为size,遍历一次后若index还是size,说明插在尾部
int index=size;
for(int i=0;i<size;i++){
if(key<=arr[i]){
index=i;
break;
}
}
//后移操作
for(int j=size;j>index;j--){
arr[j]=arr[j-1];
}
arr[index]=key;
size=size+1;
return index;
}
删除操作
/**
*
* @param arr 删除操作的数组
* @param size 已经存储的元素个数
* @param key 删除的元素的值
* @return
*/
//本方法适用于删除第一个值为key的元素
public static int delete(int[] arr,int size,int key){
int index=-1;
for(int i=0;i<size;i++){
if(arr[i]==key){
index=i;
break;
}
}
//前移操作
if(index!=-1){
for(int j=index;j<size-1;j++){
arr[j]=arr[j+1];
}
size=size-1;
}
return size;
}