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

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);
	}

}

猜你喜欢

转载自767148424.iteye.com/blog/2344750