数组和链表的区别及使用场景

Java中已经定义好了一个长度可变数组:ArrayList

数组的特点:内存地址连续

优点:数据是存放在一个连续的内存地址上,查找效率比较高

缺点:在改变数据个数的时候[增加,插入,删除]效率比较低

链式列表:[链表] 数据在内存中可以在任意位置,通过引用来关联数据

1.MyArray 数组

package com.newer.cjl.api;

/**
* 自定义长度可变的数组[泛型]
*
* @author Administrator
*
*/
public class MyArray<E> {

// 定义一个长度为0的初始数组
private Object[] src = new Object[0];

/**
* 存放数据
*
* @param s
* 要存放的数据
*/
public void add(E s) {
// 定义一个新数组长度是源数组长度+1
Object[] dest = new Object[src.length + 1];
// 将原数组的数据拷贝到新数组中
System.arraycopy(src, 0, dest, 0, src.length);
// 将新数据放到新数组的最后一个位置
dest[dest.length - 1] = s;
// 将原数组指向新数组
src = dest;

}

/**
* 取出数据
*
* @param index
* 要取出的数据的下标
*/
public E get(int index) {
Object s = src[index];
return (E)s;
}

/**
* 根据下标删除数据
*
* @param index
* 要删除的数据的下标
*/
public void delete(int index) {
Object[] dest = new Object[src.length-1];
//将下标小于index的拷贝到新数组对应的下标位置
System.arraycopy(src, 0, dest, 0, index);

//将下标大于index的拷贝到新数组下标的位置为原数组的下标位置-1
System.arraycopy(src, index+1, dest, index, src.length-index-1);
//将src指向新数组
src=dest;
}

/**
* 删除指定的数据
*
* @param s
* 要删除的数据,如果有重复的数据,就删除下标最小的
*/
public void delete(E s) {
int t=-1;
for(int i=0;i<src.length;i++){
if(src[i].equals(s)){
t=i;
break;
}
}
//如果s在数组中出现过,t一定会>=0
if(t>=0){
delete(t);
}
}

/**
* 将数据插入到指定位置
* @param index 要插入的位置
* @param s 要插入的数据
*/
public void insert(int index,E s){
Object[] dest = new Object[src.length+1];
//将新数据放到新数组的指定位置
dest[index]=s;

//将下标小于index的数据拷贝到新数组对应的下标位置
System.arraycopy(src, 0, dest, 0, index);
//将下标>=index的数据宝贝到新数组下标+1的位置
System.arraycopy(src, index, dest, index+1, src.length-index);

src=dest;

}

/**
* 修改数据
*
* @param index
* 要修改的数据的下标
* @param s
* 修改后的数据
*/
public void update(int index, E s) {
src[index] = s;
}

/**
* 获得数据个数
*/
public int size() {
return src.length;
}
}

2.Main主函数实现

package com.newer.cjl.api;

import java.util.ArrayList;

/**
* 自定义长度可变数组的测试类
*
* @author Administrator
*
*/
public class Main {

public static void main(String[] args) {
// // 创建数组对象
// MyArray<String> arr = new MyArray<String>();
// // 增加数据
// arr.add("AA");
// arr.add("BB");
// arr.add("CC");
// arr.add("DD");
// arr.add("EE");
// arr.add("FF");
//
//
// arr.insert(5, "新来的");
//
// // 取出数据
// for (int i = 0; i < arr.size(); i++) {
// String s = arr.get(i);
// System.out.println(s);
// }


ArrayList<Integer> arr = new ArrayList<Integer>();
arr.add(100);
arr.add(200);
arr.add(300);

for(int i=0;i<arr.size();i++){
int t = arr.get(i);
System.out.println(t);
}

}
}

3.双向链表

package com.newer.cjl.api;

/**
* 自定义链表类【双向链表】
*
* @author Administrator
*
*/
public class MyLinkList<E> {

// 初始状态下,链表没有任何结点,头结点为null,尾结点为null
private Node<E> head = null;
private Node<E> last = null;
private int num = 0;// 数据个数

// 增加数据
public void add(E e) {
// 根据数据创建结点对象
Node<E> node = new Node<E>(e);

// 如果链表中已经有结点,就将node作为last的下一个结点
if (last != null) {
last.next = node;
node.front = last;
last = node;
} else {
// 如果链表中还没有结点,node就是第一个结点
// 既是头结点,又是尾结点
head = node;
last = node;
}
num++;

}

public void insert(int index, E e) {
// 创建新结点
Node<E> node = new Node<E>(e);
// 找到index位置的结点
Node<E> n1 = getNode(index);
// 找到n1的前一个结点
Node<E> n2 = n1.front;

n2.next = node;
node.front = n2;

node.next = n1;
n1.front = node;

num++;
}

public void delete(int index) {

}

public void delete(E e) {

}

public void update(int index, E e) {
Node<E> n1 = getNode(index);
n1.data = e;
}

public E get(int index) {
Node<E> node = getNode(index);
return node.data;
}

//根据内容确定下标
private int getIndex(E e){
int index=-1;
Node<E> n = head;
while(n!=null){
index++;
if(n.data.equals(e)){
break;
}
n=n.next;
}
return index;
}

public int getIndex2(E e){
for(int i=0;i<num;i++){
E e2 = get(i);
if(e2.equals(e)){
return i;
}
}
return -1;

}

//根据下标确定结点
private Node<E> getNode(int index) {
int t = -1;
if (index >= 0 && index < num) {
Node<E> n = head;

while (n != null) {
t++;
if (t == index) {
break;
}
n = n.next;

}
return n;

} else {
// 抛出异常
throw new IndexOutOfBoundsException("下标超出边界!index:" + index
+ ",size:" + num);
}
}


public int size() {
return num;
}

}

// 内部的结点类,主要为MyLinkList类服务
class Node<E> {
// 结点的数据
E data;
// 对下一个结点的引用
Node<E> next;
// 对前一个结点的引用
Node<E> front;

// 创建结点对象的时候必须指定数据
public Node(E e) {
data = e;
}

}

4、主函数Main实现

package com.newer.cjl.api;

public class Main4 {

public static void main(String[] args) {
MyLinkList<String> list = new MyLinkList<String>();

list.add("AA");
list.add("BB");
list.add("CC");
list.add("BB");
list.add("DD");

// //测试add方法是否正确
// System.out.println(list.last.data);
// Node<String> node = list.last.front;
// while(node!=null){
// System.out.println(node.data);
// node = node.front;
//
// }

// list.insert(2, "EE");
// list.update(3, "FF");
//
// for (int i = 0; i < list.size(); i++) {
// String s = list.get(i);
// System.out.println(s);
// }

int t = list.getIndex2("BB");
System.out.println(t);
}

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值