背景
表现优秀程序,是选择合适的数据结构和优秀的算法的必然结果,作为一名务实、精进的程序员,对数据结构的学习,熟练,自然成了必要的课程。闲话不多说,程序中的数据结构,是与语言无关的,常见的数据结构有:
- 数组(静态数组、动态数组)、
- 线性表、链表(单向链表、双向链表、循环链表)
- 队列
- 堆
- 树(二叉树、查找树、平衡树、线索树、线索树)
在接下来的学习中,会对以上各种数据结构进行操作(add/get/delete),并简单的评估其效率(时空复杂度);在本博客中,尽量精准到概念化、原理画、源码化,所以会有很多概念梳理,原理、源码分析,看到的大神勿喷;
开始
一 数组的定义
数组是最简单的数据结构,根据定义方式有:
1.静态数组(Java中的,数组)
数组定义后,其开辟的内存空间大小已定,不能再追加元素
int []arr=new int[]{1,2,3,4};//静态初始化
int []arr1=new int [10];//动态初始化
arr1[0]=1;
arr1[1]=2;
....
2.动态数组(Java中的ArrayList)
ArrayList的本质还是数组,因为数组定义后,其开辟的内存空间大小已定,不能再追加元素;ArraList在数组的基础上,使用java.util.Arrays这个工具类,将数组扩容,再将原数组元素,复制到一个新数组;
我们看下面这个方法,ArrayList中add() corecode
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;//原数组长度
int newCapacity = oldCapacity + (oldCapacity >> 1);//扩容后长度
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);//返回扩容后的数组
}
问题来了,那这个Arrays是如何实现,点开Arrays.copyOf(elementData, newCapacity);
public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
T[] copy = ((Object)newType == (Object)Object[].class)
? (T[]) new Object[newLength]
: (T[]) Array.newInstance(newType.getComponentType(), newLength);//获得一个新数组
//调用native的方法,native的方法是用c写的
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}
之分别;根据数据是否有序,又分为:
1.无序数组:数据是没有规律的
2.有序数组;数据经过排序
数组的,add操作速度很快,为:o(1),但是查找和杀出比较慢,为:o(N)
二.数组元素的排序
定义:有数组,int [] arr=new int[]{95, 13, 88, 49, 12, 25, 84, 63, 73, 96, 70, 45, 38, 47, 53, 69, 81, 73, 33, 32},将数组按照由小到的顺序实现排序;
1冒泡排序
分析:将素组中元素,从左到右,一次两两比较大小,比较大的数字,交互到右边
然后在以此,重复N-1次;
代码实现:
//冒泡排序实现2
public static void bubbleSortImp(){
int[] newArr = productArray(20);
int size=newArr.length;
int temp;
for(int i=size-1;i>0;i--){//指定外层的,遍历
for(int j=i;j>0;j--){//内层的,相邻数字比较,及当前位置的移动
temp=newArr[i];
if(newArr[i]<newArr[j-1]){
newArr[i]=newArr[j-1];
newArr[j-1]=temp;
}
}
}
StringBuffer buffer = new StringBuffer();
buffer.append("NewArray:");
buffer.append(Arrays.toString(newArr));
System.out.println(buffer.toString());
}
结果:
测试数组:OldArray:[95, 13, 88, 49, 12, 25, 84, 63, 73, 96, 70, 45, 38, 47, 53, 69, 81, 73, 33, 32]
排序结果:NewArray:[12, 13, 25, 32, 33, 38, 45, 47, 49, 53, 63, 69, 70, 73, 73, 81, 84, 88, 95, 96]
2.选择排序
分析:将数组中数据,从左到右,依次取数字和左边数字比较,如果左边数字比较小则将当前数组元素和左边数字交换
代码:
//选择排序实现
public static void selectSortImp(){
int[] newArr = productArray(20);
int size=newArr.length;
int temp;
for(int i=0;i<size-1;i++){
temp=newArr[i];
for(int j=i+1;j<=size-1;j++){
if(newArr[i]>newArr[j]){
newArr[i]=newArr[j];
newArr[j]=temp;
}
}
}
StringBuffer buffer = new StringBuffer();
buffer.append("NewArray:");
buffer.append(Arrays.toString(newArr));
System.out.println(buffer.toString());
}
结果:
测试数组:OldArray:[12, 57, 86, 75, 50, 13, 4, 55, 81, 62, 91, 61, 67, 14, 66, 53, 42, 78, 12, 44]
排序结果:NewArray:[4, 12, 12, 42, 44, 61, 66, 78, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 91]
3.插入排序
分析:
代码实现:
// 插入排序实现
public static void insertSortImp() {
int[] newArr = productArray(20);
int size = newArr.length;
int j = 0;
long start=System.currentTimeMillis();
for (int i = 1; i < size; i++) {
int temp = newArr[i];
j = i;
while (j >0 && newArr[j - 1]>= temp) {//找到打破有序的元素
newArr[j] = newArr[j - 1];//交互
j--;
}
newArr[j] = temp;//将j号元素插入部分有序的最后位置
}
long end=System.currentTimeMillis();
StringBuffer buffer = new StringBuffer();
System.out.println("insertSortImp".concat("\n"));
buffer.append("NewArray:");
buffer.append(Arrays.toString(newArr));
System.out.println(buffer.toString());
System.out.println("CostTime=".concat(String.valueOf(end-start)));
}
测试数组:OldArray:[17, 29, 21, 30, 75, 83, 95, 52, 96, 46, 9, 43, 16, 71, 8, 68, 0, 66, 90, 92]
排序结果:NewArray:[0, 8, 9, 16, 17, 21, 29, 30, 43, 46, 52, 66, 68, 71, 75, 83, 90, 92, 95, 96]
对象的排序
以上我们操作的都是基本数据类型,但是实际开发中我们经常要操作对象类型数据
,对一组对象进行排序,
例如:将十个人,按照年龄大小排序,并且输出排序结果;
分析:我们要实现这两个接口的一个:1.Comparable
Comparator,使用的时候是这样实现的,comparetor要实现的方法:
@Override
public int compare(Person o1, Person o2) {
// TODO Auto-generated method stub
//此处person类,按照年龄,从大到小,注意返回值
if (o1.getAge() > o2.getAge()) {
return 1;
} else {
return 0;
}
}
Comparable与之类似
@Override
public int compareTo(Person o) {
if(this.age>o.age){
return 1;
}else{
return 0;
}
完整过程:
Person person = new Person();
person.setAge(20);
person.setName("yangliang");
Person person2 = new Person();
person2.setAge(18);
person2.setName("beauty");
Person person3 = new Person();
person3.setAge(15);
person3.setName("fdfas");
....
ArrayList<Person> list = new ArrayList<Person>();
list.add(person);
list.add(person2);
list.add(person3);
....
Collections.sort(list, new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
// TODO Auto-generated method stub
if (o1.getAge() > o2.getAge()) {
return 1;
} else {
return 0;
}
}
});
排序结果:
[Person [age=20, name=yangliang], Person [age=18, name=beauty], Person [age=15, name=fdfas]....]
这里我们看到一个Collections,工具类,后面再详细介绍