Java数据结构

一、数据结构

1、什么是数据结构?

  数据结构指的是计算机对数据存储的一种安排。

二、数据存储之数组存储

1、数组存储数据的格式

  数据类型[ ]   变量名 = new   int[ ];    这是动态存储

2、数组存储的特点

  ①数组一旦创建,长度是固定的;

  ②数组可以存储多个数据相同的数据类型。

三、自定义一个可以存储任意长度、任意数据类型的引用数据类型(Java中已经有这个类,是使用的数组实现的,但是还是建议自己写一下,锻炼思维、巩固基础)

/*
*定义一个类来存储我们的数据,后续的所有方法都在这个类中进行
*
*/
class DateConstructMethod{





}
View Code

  既然可以存储任意数据类型,那么我们应该想到面向对象编程,所以我们可以从以下几个方面来实现这个需求:

  ①实现一个可以自动扩容的int数组,里面有一个add方法来添加数据和一个getLength方法来获取数组的元素个数,并且覆写Object中的toString方法可以打印出list类型的表;

  ②实现可以存储任意数据类型;

  ③、实现数组的增删改查方法。

1、实现一个指定长度的数组,里面有一个add方法来添加数据和一个getLength方法来获取数组的元素个数,并且覆写Object中的toString方法可以打印出list类型的表;

int[] elements = new int[10];
int size;//记录元素的个数
/**
 * 定义的这个add方法是往elements数组里面添加元素的,但是当添加的元素个数大于数组长度时会抛出异常,
 * 因此我们做了一个判断,当元素个数大于等于数组长度时,那么就会生成一个新数组newElements,并且将
 * elements数组中的数据全部拷贝到newElements数组中,然后newElements数组将地址赋值给elements,
 * 再往里面添加元素。
 * 注意:①此处数组扩容你可以选择一次扩容一个、按百分比扩容、按倍数扩容等;
 *        ②size每次都在自增,当添加完元素后,size的大小应该等于元素个数。
 * @param value
 */
public void add(int value){
    if(size >= elements.length){
        int[] newElements = new int[2*elements.length];
        System.arraycopy( elements, 0, newElements, 0, size);
        elements = newElements;
        
    }
    elements[size++] = value;
}
public int getLength(){
    return size;
}
@Override
/**
 * 覆写Object类中的toString方法,因为在刚添加完元素后,我们的elements数组中可能有部分null值,
 * 但是我们在打印成list表时又不希望看到,所以我们创建了一个不含null值长度的新数组,并将数据拷贝进去,
 * 然后利用Arrays.toString()方法将新数据以list表的形式return出去。
 */
public String toString() {
    int[] newElements = new int[size];
    System.arraycopy(elements, 0, newElements, 0, size);
    return Arrays.toString(newElements);
}

2、实现可以存储任意数据类型。

  这一步非常简单,因为Object类是所有类的基类,因此Object是一种数据类型,可以存储任意数据类型,于是,我们只需要将代码中的所有int数据类型改为Object数据类型即可。

3、实现数组的增删改查方法。

/**
 * 查找指定索引出的元素
 * @param index
 * @return
 */
public Object getElementsByIndex(int index){
    if(index<0 || index>size-1){
        throw new ArrayIndexOutOfBoundsException("请输入正确的索引");
        /*
         * 今后所有不满足条件的都采用抛出异常的方式
         */
        
    }
    return elements[index];
}
/**
 * 查找指定元素第一次出现的索引
 * @param obj
 * @return
 */
public int getIndexByElements(Object obj){
    int index = -1;
    for (int i = 0; i < size; i++) {
        if(elements[i].equals(obj)){
            index = i;
            break;
        }
    }
    return index;
}
/**
 * 删除指定索引处的元素
 * 思路:想要删除某个元素其实就是将这个元素后面的元素copy过来,从开始删除的这个元素的位置一个一个的放。
 */
public void deleteElementsByIndex(int index){
    if(index<0 || index>size-1){
        throw new ArrayIndexOutOfBoundsException("请输入正确范围内的索引");
    }
    System.arraycopy(elements, index+1, elements, index, size-index-1);
    elements[size-1] = null;
    size--;
}
public void deleteElementsByElements(Object obj){
    for (int i = 0; i < size; i++) {
        int index = getIndexByElements(obj);
        if(index != -1){}
        deleteElementsByIndex(index);
        
    }
}
View Code

4、测试代码示例

import java.util.Arrays;
/**
 * 
 * 写一个能装任意数据类型的引用数据类型。
 *
 */
public class DateConstruct {
    public static void main(String[] args) {
        DateConstructMethod d = new DateConstructMethod();
        d.add(0);
        d.add(true);
        d.add(3);
        d.add(4);
        System.out.println(d);
        
        d.deleteElementsByIndex(1);
        System.out.println(d);
        
        
    
    }    
    
}

三、数据存储之链表

1、什么是链表?

  一个变量只能存出一个值,如果我们将多个变量存储到一个容器中,让其以一定的规律来存储那这就是链表。

四、定义一个数据类型来存储多个变量

1、原理

  我们前面说到过自动装箱的原理,是在Java5实现的,因此我们可以定义一个外部类和一个内部类,外部类里面定义一个add方法来添加数据和覆写toString方法将数据打印出list表,再定义两个实例属性,一个是Node node = firstNode(意思是外部类里面有个盒子,用来存储第一个对象的内存地址),另外一个是int size(用来记录存储额数据个数),这个内部类有两个实例属性,一个是Object data(要存储的数据),另外一个是Node nextNode(下一个对象的内存地址)。首先我们要知道以下几个方面:①这些数据通过add方法存储时,实际上是调用了内部类里面有一个参数的构造方法;②数据对象之间是通过内存地址相连接的(也就是外部类里面的变量node存储第一个数据对象的内存地址,第一个数据对象里面的node存储第二个数据对象的内存地址,以此类推)。

2、实现代码示例

/**
 * 数据的链表结构其实底层就是将一个一个的变量存到容器中,但是每个变量之间是散乱的,没有联系,外界也无法获取,因此我们生成一个对象,这个对象里面有两个实例属性,
 * 一个是数据值,另外一个是下一个对象的地址
 * 
 *
 */
public class Test1 {
    public static void main(String[] args) {
        Linked list = new Linked();
        list.add(1);
        list.add(true);
        System.out.println(list);
        System.out.println(list.getSize());
        
    }

}
class Linked{
    //第一个对象的地址
    private Node firstNode;
    //记录当前容器中数据的个数
    private int size;    /**
     * 这个添加方法是为了将数据加入到linked这个容器中
     * @param value
     */
    public void add(Object value){
        /*
         * 它不仅创建了对象,还传入了数据(可以这么理解:每创建一个对象,就是传入了数据,把数据看成一个球,创建对象是将这个球放进袋子中,这个对象里面还有一个
         * 属性试下一个对象的地址,正是通过下一个对象的地址才将这一个一个的对象串联起来的)
         */
        Node node = new Node(value);
        /*
         * linked容器中有一个实例属性是储存第一个数据对象的地址的,这个判断的意思是如果储存第一个数据对象地址的属性为空,那么就将传入的这个数据对象的地址复制一份赋值
         * 给它,如果不是空的,那就进行一个循环,这个循环的目的是找到那个还没有储存下一个对象的内存地址的对象,这样来将每一个对象串联起来
         */
        if(firstNode==null){
            firstNode =node;
        }else{
            //定义一个变量来储存当前对象的内存地址
            Node n = firstNode;
            while(n.nextNode!=null){
                n = n.nextNode;
            }
            //当第n个对象里面存储的下一个对象的内存地址为空的时候就将下一个对象的地址复制一份赋值给上一个对象的node。
            n.nextNode = node;
        }
        size++;
    }
    class Node{
        //储存数据
        private Object data;
        //储存下一个对象的地址
        private Node nextNode;
        //这个构造方法是用来传入数据的
        private Node(Object data){
            this.data = data;
        }
    }
    public int getSize(){
        return size;
    }
    @Override
    public String toString() {
    /*
     * 覆写的时候Object类中的toString方法
     */
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        Node n = firstNode;
        while(n!=null){
            sb.append(n.data);
            if(n.nextNode != null){
                sb.append(",");
            }
            n = n.nextNode;
        }
        sb.append("]");
        
        return sb.toString();
        /*
         * 返回这个对象(前提是已经是字符串)。
         */
        
    }
        
}
View Code
原文地址:https://www.cnblogs.com/limengkun/p/10687103.html