数组
无序数组
插入(根据数组元素值,而不是根据数组的索引)
新的数据项总是插在数组中的第一个空位上,并且由于数组中已有的数据项个数已知,所以算法知道这个空位的具体位置,新的数据项只是简单的插入到下一个可用的空间中。
时间复杂度:O(1)
/**
* 插入操作
*
* @param value
*/
public void insert(int value) {
a[nElems] = value;
nElems++;
}
查找(根据数组元素值,而不是根据数组的索引)
数据项为N,则一个数据项的平均查找时间为N/2,在最坏的情况下,查找时间为N。这种查找也叫线性查找
时间复杂度:O(N)
/**
* 根据关键值查找
*
* @param searchKey
* @return
*/
public boolean find(int searchKey) {
int i;
for (i = 0; i < nElems; i++) {
if (a[i] == searchKey) {
break;
}
}
//已经查找完毕,没有找到
if (i == nElems) {
return false;
} else {
return true;
}
}
删除(根据数组元素值,而不是根据数组的索引)
只有在查找到要删除的数据项之后,才能删除它。
时间复杂度:O(N)
/**
* 根据关键值删除
*
* @param value
*/
public boolean delete(int value) {
int i;
for (i = 0; i < nElems; i++) {
if (a[i] == value) {
break;
}
}
//已经查找完毕,没有找到
if (i == nElems) {
return false;
} else {
for (int k = i; k < nElems; k++) {
a[k] = a[k + 1];
}
nElems--;
return true;
}
}
完整案例(假设元素不重复)
package test27;
/**
* 无序数组(元素不重复)
* 插入:一次移动
* 根据值删除和查找:平均需要n/2次比较
* 根据值删除:还需要n/2次移动
* *
* 无序数组(元素可能重复)
* 插入:一次移动
* 根据值删除和查找:n次比较
* 根据值删除:多于n/2次移动
*/
public class HighArray {
private int[] a;
//记录数组的实际长度
private int nElems;
public HighArray(int max) {
a = new int[max];
nElems = 0;
}
/**
* 插入操作
*
* @param value
*/
public void insert(int value) {
a[nElems] = value;
nElems++;
}
/**
* 展示
*/
public void display() {
for (int i = 0; i < nElems; i++) {
System.out.print(a[i] + " ");
}
System.out.println();
}
/**
* 根据关键值查找
*
* @param searchKey
* @return
*/
public boolean find(int searchKey) {
int i;
for (i = 0; i < nElems; i++) {
if (a[i] == searchKey) {
break;
}
}
//已经查找完毕,没有找到
if (i == nElems) {
return false;
} else {
return true;
}
}
/**
* 根据关键值删除
*
* @param value
*/
public boolean delete(int value) {
int i;
for (i = 0; i < nElems; i++) {
if (a[i] == value) {
break;
}
}
//已经查找完毕,没有找到
if (i == nElems) {
return false;
} else {
for (int k = i; k < nElems; k++) {
a[k] = a[k + 1];
}
nElems--;
return true;
}
}
}
package test27;
/**
* 本例示范的是 无序数组(元素不重复)
*/
public class HighArrayApp {
public static void main(String[] args) {
int maxSize = 100;
HighArray arr = new HighArray(maxSize);
arr.insert(77);
arr.insert(99);
arr.insert(44);
arr.insert(55);
arr.insert(22);
arr.insert(88);
arr.insert(11);
arr.insert(00);
arr.insert(66);
arr.insert(33);
arr.display();
int searchKey = 35;
if(arr.find(searchKey)){
System.out.println("找到"+searchKey);
}else{
System.out.println("未找到"+searchKey);
}
arr.delete(00);
arr.delete(55);
arr.delete(99);
arr.display();
}
}
运行结果如下:
有序数组
插入(根据数组元素值,而不是根据数组的索引)
比无序数组的插入多了一步,就是先查找到要插入的位置,才能进行插入
时间复杂度:O(N)
/**
* 有序数组的插入,
* 首先要查找插入的位置,然后才能进行插入
* @param value
*/
public void insert(int value) {
int j;
for (j = 0; j < nElems; j++) {
//查找到了要插入元素的位置j,跳出循环
if(a[j]>value){
break;
}
}
//腾出位置
for (int k = nElems; k > j; k--) {
a[k] = a[k-1];
}
a[j] = value;
nElems++;
}
查找(根据数组元素值,而不是根据数组的索引)
有序数组的查找使用二分查找法
时间复杂度:O(logN)
/**
* 根据关键值查找
* 有序数组,使用二分查找算法
* @param searchKey
* @return
*/
public int find(int searchKey) {
int lowerBound = 0;
int upperBound = nElems - 1;
int curIn;
while (true){
curIn = (lowerBound+upperBound)/2;
if(a[curIn]== searchKey){
return curIn;
}else if(lowerBound>upperBound){
//表明未找到
return -1;
}else{
if(a[curIn]<searchKey){
lowerBound = curIn+1;
}else{
upperBound = curIn-1;
}
}
}
}
删除(根据数组元素值,而不是根据数组的索引)
删除也是先找到元素位置(二分法查找),然后进行删除
时间复杂度:O(N)
/**
* 根据关键值进行删除
* 使用二分查找算法先查找到该元素的索引位置
* 然后进行删除
* @param value
*/
public boolean delete(int value) {
int j = find(value);
if(j == -1){
return false;
}else{
for (int k = j; k < nElems; k++) {
a[k] = a[k+1];
}
nElems --;
return true;
}
}
完整案例(假设元素不重复)
package test28;
/**
* 有序数组
*/
public class OrdArray {
private int[] a;
//记录数组的实际长度
private int nElems;
public OrdArray(int max) {
a = new int[max];
nElems = 0;
}
/**
* 有序数组的插入,
* 首先要查找插入的位置,然后才能进行插入
* @param value
*/
public void insert(int value) {
int j;
for (j = 0; j < nElems; j++) {
//查找到了要插入元素的位置j,跳出循环
if(a[j]>value){
break;
}
}
//腾出位置
for (int k = nElems; k > j; k--) {
a[k] = a[k-1];
}
a[j] = value;
nElems++;
}
public void display() {
for (int i = 0; i < nElems; i++) {
System.out.print(a[i] + " ");
}
System.out.println();
}
/**
* 根据关键值进行删除
* 使用二分查找算法先查找到该元素的索引位置
* 然后进行删除
* @param value
*/
public boolean delete(int value) {
int j = find(value);
if(j == -1){
return false;
}else{
for (int k = j; k < nElems; k++) {
a[k] = a[k+1];
}
nElems --;
return true;
}
}
/**
* 根据关键值查找
* 有序数组,使用二分查找算法
* @param searchKey
* @return
*/
public int find(int searchKey) {
int lowerBound = 0;
int upperBound = nElems - 1;
int curIn;
while (true){
curIn = (lowerBound+upperBound)/2;
if(a[curIn]== searchKey){
return curIn;
}else if(lowerBound>upperBound){
//表明未找到
return -1;
}else{
if(a[curIn]<searchKey){
lowerBound = curIn+1;
}else{
upperBound = curIn-1;
}
}
}
}
}
package test28;
public class OrderedApp {
public static void main(String[] args) {
int maxSize = 100;
OrdArray arr = new OrdArray(maxSize);
arr.insert(77);
arr.insert(99);
arr.insert(44);
arr.insert(55);
arr.insert(22);
arr.insert(88);
arr.insert(11);
arr.insert(00);
arr.insert(66);
arr.insert(33);
arr.display();
int searchKey = 55;
if(arr.find(searchKey)!=-1){
System.out.println("找到"+searchKey);
}else{
System.out.println("未找到"+searchKey);
}
arr.delete(00);
arr.delete(55);
arr.delete(99);
arr.display();
}
}
运行结果如下:
时间复杂度分析
场景分析
有序数组适合公司雇员的数据库,增加和删除操作比较少,一般删除都是逻辑删除(禁用),查询操作比较多。
无序数组适合零售商店的存货清单,增加操作较多。无序数组的生活场景应用较多