基于数组的容器类实现 和 基于链表结构的容器类实现
1、数据结构
概念 :数据结构是计算机存储、组织数据的方式。 简单理解:可以看成是对数据存储的一种方式
常见的数据结构:
数组:数组(Array)是一种线性表数据结构。它用一组连续的内存空间,来存储一组具有相同类型的数据。
链表: 一种动态的线性的数据结构 , 优点: 动态创建,节省空间,头部添加容易 , 缺点:空间上不连续,查找困难。只能从头开始一个一个找
队列:FIFO 先进先出原则
堆栈:FILO 先进后出原则
2、数组结构和链表结构的区别
1、数组是将元素在内存中顺序存储,由于每个元素占用内存相同,可以通过下标迅速访问数组中任何元素。但是如果要在数组中增加或者删除一个元素,需要移动大量元素。
链表将在内存中零散 随机的一些对象通过对象的引用将所有对象的连接起来。如果要访问链表中一个元素,需要从第一个元素开始,一直找到需要的元素位置。链表动态地进行存储分配,可以适应数据动态地增减的情况,且可以方便地插入、删除数据项。
所以,数组查询快,增删慢。链表查询慢,增删快 。
1.从逻辑结构角度来看:
数组必须事先定义长度(元素个数),不能适应数据动态地增减的情况。当数据增加时,可能超出原先定义的元素个数;当数据减少时,造成内存浪费。
链表动态地进行存储分配,可以适应数据动态地增减的情况,且可以方便地插入、删除数据项。(数组中插入、删除数据项时,需要移动其它数据项)
2.从时间复杂度看:
数组利用下标定位,时间复杂度为O(1),链表定位元素时间复杂度O(n);
数组插入或删除元素的时间复杂度O(n),链表的时间复杂度O(1)。
3、基于数组的容器类实现
import java.util.Arrays;
public class Container {
private int num = 0; //容器类保存元素的个数
private Object [] contain; //定义个保存任何类型的容器
// 无参的构造方法
public Container(){
this(5);
}
//有参的构造方法
public Container(int length){
this.contain = new Object[length];
}
//获取容器元素个数
public int getNum(){
return num;
}
//给容器添加元素
public void add(Object value){
//if(firstIndex(value)==-1){} 用于去除重复元素
if(num == this.contain.length){
Object[] temp = new Object[this.contain.length*2]; //扩容
System.arraycopy(contain, 0, temp, 0, num);
this.contain = temp;
}
contain[num] = value;
num++;
}
//重写toString 方法
public String toString(){
Object[] temp =Arrays.copyOf(contain, num);
return Arrays.toString(temp);
}
//容器的其他方法
//1.根据下标获取元素
public Object getElementByIndex(int index){
if(index>=0 && index<num){
return contain[index];
}
return -1;
}
//2.获取元素第一次出现的位置的下标
public int firstIndex(Object obj){
for (int i = 0; i < contain.length; i++) {
if(obj.equals(contain[i])){
return i;
}
}
return -1;
}
//3.通过指定出现的次数,查找指定元素的下标
public int indexOf(Object obj,int count){
for (int i = 0; i < contain.length; i++) {
if(obj.equals(this.contain[i])){
count--;
if(count==0){
return i;
}
}
}
return -1;
}
//4.指定索引 删除对应位置上的元素
public void delete(int index){
if(index>=0 && index<num){
this.contain[index] = null;
//将null值后的所有元素依次向前移一位
for (int i = index; i < contain.length-1; i++) {
this.contain[i] = this.contain[i+1];
}
Object[] temp = new Object[num];
temp = Arrays.copyOf(contain,temp.length-1);
this.contain = temp;
num--;
}
}
//5.删除 第一次出现 的指定元素
public void deleteFirstElement(Object obj){
if(firstIndex(obj) != -1){
delete(firstIndex(obj));
}
}
//6.删除 所有的指定元素 核心思想:永远删除的是第一个元素,直到容器中没有该指定元素(返回负数)
public void deleteElement(Object obj){
while(firstIndex(obj) != -1){
delete(firstIndex(obj));
}
}
//7.删除 所有元素
public void empty(){
this.num = 0;
Arrays.fill(contain, null);
}
}
4、基于链表结构的容器类实现
/*
* 容器类: 保存 :1. 第一个节点的引用(地址),根据这个地址能够找到下一个节点。
* 2. 节点的个数。
*/
public class LinkList {
private Node first;
private int size;
//容器类添加元素的方法
public void add(Object obj){
//1. 将要添加的元素封装到 节点类中、
Node ele = new Node(obj);
//2.当first引用为null时,直接将first指向 上面创建的ele对象(里面保存了要添加的元素)。
// 当first引用指向了 一个Node类中的对象,先将first引用保存到Node类中temp这个引用变量(相当于获取了第一个节点)。
//然后通过while循环判断temp.getNext(),即这个对象的下一个引用节点是否为null,如果不为空,将 temp.getNext()赋给temp,继续循环判断。
// 直到节点的 next引用 为null时,ele对象保存的下一个引用节点中。 外围 size++
if (first == null) {
first = ele;
}else{
Node temp = first; //获取第一个节点
while(temp.getNext() != null){
temp = temp.getNext();
}
temp.setNext(ele);
}
size++;
}
//重写toString方法,打印容器类的所有元素
public String toString(){
StringBuffer sb = new StringBuffer("[");
Node temp = first;
while(temp.getNext()!=null){
sb.append(temp.getObj()+" ");
temp = temp.getNext();
}
sb.append(temp.getObj()+"]");
return sb.toString();
}
}
/**
* 节点类:保存 节点数据元素 和 下一个节点的引用。
*作用:我想再强调一下数据结构的作用是为数据寻找一个合适的载体,让数据的操作更加快捷。
Node只不过是一个辅助工具,并不会暴露在外。它与数据相对应,又使数据按链式排布,
操纵节点也就等于操纵数据,就像提线木偶,我们操作的是"观众"所看不见的线,而不是木偶的各个肢体本身
*/
public class Node {
private Object obj; //节点数据元素
private Node next; //下一个节点的引用(地址)
//setter/getter方法
public Object getObj() {
return obj;
}
public void setObj(Object obj) {
this.obj = obj;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
//有参的构造方法,给节点元素赋值。
public Node(Object obj){
this.obj = obj;
}
}

浙公网安备 33010602011771号