数据结构
数据结构是计算机存储、组织数据的方式,指相互之间存在一种或多种特定关系的数据元素的集合。
常见数据结构有:
1、数组 插入快 查找删除慢 大小固定 元素单一
2、有序数组 查找快 插入删除慢 大小固定 元素单一
3、栈 先进后出
4、队列 先进先出
5、链表 插入删除快 查找慢
6、二叉树 树是平衡的则增删改都快,删除算法复杂
7、红黑树 增删改都快,树总是平衡的,算法复杂
8、2-3-4树 增删改都快,树总是平衡的, 算法复杂
9、哈希表 知道关键字则查询插入都快,删除慢,不知道关键字存取慢,对存储空间使用不充分
10、堆 插入删除快,对最大数据项存取快,对其它数据项慢‘
11、图 对现实世界建模 有些算法慢且复杂
算法
算法简单来说就是解决问题的步骤
在Java中,算法通常都是由类的方法来实现的。前面的数据结构,比如链表为啥插入、删除快,而查找慢,平衡的二叉树插入、删除、查找都快,这都是实现这些数据结构的算法所造成的。
算法的特征:
1、有穷性:对于任意一组合法输入值,在执行又穷步骤之后一定能结束,即:算法中的每个步骤都能在有限时间内完成。
2、确定性:在每种情况下所应执行的操作,在算法中都有确切的规定,使算法的执行者或阅读者都能明确其含义及如何执行。并且在任何条件下,算法都只有一条执行路径。
3、可行性:算法中的所有操作都必须足够基本,都可以通过已经实现的基本操作运算有限次实现之。
4、有输入:作为算法加工对象的量值,通常体现在算法当中的一组变量。有些输入量需要在算法执行的过程中输入,而有的算法表面上可以没有输入,实际上已被嵌入算法之中。
5、有输出:它是一组与“输入”有确定关系的量值,是算法进行信息加工后得到的结果,这种确定关系即为算法功能。
算法设计原则:
1、正确性
2、可读性
3、健壮性
4、高效率与低存储量需求:通常算法效率值得是算法执行时间;存储量是指算法执行过程中所需要的最大存储空间,两者都与问题的规模有关。
数组
数组的局限性分析:
1、插入快,对于无序数组,上面我们实现的数组就是无序的,即元素没有按照从大到小或者某个特定的顺序排列,只是按照插入的顺序排列。无序数组增加一个元素很简单,只需要在数组末尾添加元素即可,但是有序数组却不一定了,它需要在指定的位置插入。
2、查找慢,当然如果根据下标来查找是很快的。但是通常我们都是根据元素值来查找,给定一个元素值,对于无序数组,我们需要从数组第一个元素开始遍历,直到找到那个元素。有序数组通过特定的算法查找的速度会比无需数组快,后面我们会讲各种排序算法。
3、删除慢,根据元素值删除,我们要先找到该元素所处的位置,然后将元素后面的值整体向前面移动一个位置。也需要比较多的时间。
4、数组一旦创建后,大小就固定了,不能动态扩展数组的元素个数。如果初始化你给一个很大的数组大小,那会白白浪费内存空间,如果给小了,后面数据个数增加了又添加不进去了。
简单排序算法
冒泡算法的运作规律如下:
1、比较相邻的元素。如果第一个比第二个大,就交换他们两个。
2、对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数(也就是第一波冒泡完成)。
3、针对所有的元素重复以上的步骤,除了最后一个。
4、持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
public class BubbleSort { public static int[] sort(int[] array){ for(int i=1;i<array.length;i++){ boolean flag = true; for(int j =0;j<array.length-i;j++){ if(array[j]>array[j+1]){ int temp = array[j]; array[j] = array[j+1]; array[j+1] = temp; flag = false; } } if(flag){ break; } } return array; } public static void main(String[] args) { int[] array ={3,2,5,6,8,7,9,1,4}; Arrays.stream(array).forEach(System.out::println); array = sort(array); Arrays.stream(array).forEach(System.out::println); } }
选择排序运作规律:
1、从待排序序列中,找到关键字最小的元素
2、如果最小元素不是待排序序列的第一个元素,将其和第一个元素互换
3、从余下的 N - 1 个元素中,找出关键字最小的元素,重复(1)、(2)步,直到排序结束
public class ChoiceSort { public static int[] sort(int[] array){ for(int i=0;i<array.length;i++){ for(int j =i+1;j<array.length;j++){ if(array[i]>array[j]){ int temp = array[i]; array[i] = array[j]; array[j] =temp; } } } return array; } public static void main(String[] args) { int[] array ={3,2,5,6,8,7,9,1,4}; Arrays.stream(array).forEach(System.out::println); array = sort(array); Arrays.stream(array).forEach(System.out::println); } }
直接插入排序:
基本思想是每一步将一个待排序的记录,插入到前面已经排好序的有序序列中去,直到插完所有元素为止。
public class InsertSort { public static int[] sort(int[] array){ for(int i =1;i<array.length;i++){ int temp =array[i]; int j =i; while(j>0 && temp <array[j-1]){ array[j] =array[j-1]; j--; } array[j] = temp; } return array; } public static void main(String[] args) { int[] array ={3,2,5,6,8,7,9,1,4}; Arrays.stream(array).forEach(System.out::println); array = sort(array); Arrays.stream(array).forEach(System.out::println); } }
冒泡、选择、插入用大 O 表示法都需要 O(N2) 时间级别。一般不会选择冒泡排序,虽然冒泡排序书写是最简单的,但是平均性能是没有选择排序和插入排序好的。
选择排序把交换次数降低到最低,但是比较次数还是挺大的。当数据量小,并且交换数据相对于比较数据更加耗时的情况下,可以应用选择排序。
在大多数情况下,假设数据量比较小或基本有序时,插入排序是三种算法中最好的选择。
基于数组实现栈
这里顺带做个小测试,证明java中泛型是一个语法糖,仅在编译时起作用,当我们使用反射时,就可以越过泛型检查
public class ArrayStock<E>{ private Object[] elements; private int top; private int size; public ArrayStock(){ this.elements = new Object[10]; this.top = -1; this.size = 10; } public ArrayStock(int size) { if(size<=0){ throw new IllegalArgumentException("size不能小于0"); } this.elements = new Object[size]; this.top = -1; this.size = size; } public E push(E e){ if(size<= top+1){ grow(); } elements[++top] = e; return e; } // public E poll() { // if(top==-1){ // throw new EmptyStackException(); // } // E e =(E) elements[top]; // elements[top--] = null; // // return e; // } public Object poll() { if(top==-1){ throw new EmptyStackException(); } Object e = elements[top]; elements[top--] = null; return e; } private void grow(){ System.out.println("kuorong "); int oldCapacity = size; int newCapacity = oldCapacity<<1; Object[] newArray = new Object[newCapacity]; System.arraycopy(elements,0,newArray,0,size); this.elements = newArray; this.size = newCapacity; } public static void main(String[] args) throws Exception{ ArrayStock<String> arrayStock = new ArrayStock(3); arrayStock.push("asd"); Method method =ArrayStock.class.getDeclaredMethod("push",Object.class); method.invoke(arrayStock,13); arrayStock.push("sdf"); arrayStock.push("qwe"); arrayStock.push("sdfsdfsf"); System.out.println(arrayStock.poll()); System.out.println(arrayStock.poll()); System.out.println(arrayStock.poll()); System.out.println(arrayStock.poll()); System.out.println(arrayStock.poll()); } }
基于数组实现循环队列和优先级队列
public class ArrayQueue { private Object[] queueArray; private int maxSize; private int front; private int rear; private int items; public ArrayQueue(){ this.queueArray = new Object[3]; maxSize =3; front =0; rear = -1; items = 0; } public void push(Object o){ if(isFull()){ System.out.println("已满"); }else{ if(rear ==maxSize-1){ rear =-1; } queueArray[++rear] = o; items++; } } public Object poll(){ Object returnValue = null; if(!isEmpty()){ returnValue = queueArray[front]; queueArray[front] =null; front++; if(front==maxSize){ front = 0; } items--; } return returnValue; } private boolean isFull(){ return items ==maxSize; } public boolean isEmpty(){ return (items ==0); } public static void main(String[] args) { ArrayQueue arrayQueue = new ArrayQueue(); arrayQueue.push(12); arrayQueue.push(13); arrayQueue.push(14); System.out.println(arrayQueue.poll()); System.out.println(arrayQueue.poll()); arrayQueue.push(34); arrayQueue.push(56); arrayQueue.push(6756); arrayQueue.push(2342); System.out.println(arrayQueue.poll()); System.out.println(arrayQueue.poll()); System.out.println(arrayQueue.poll()); System.out.println(arrayQueue.poll()); } }
public class PriorityQueue { private int maxSize; private int[] priQueArray; private int nItems; public PriorityQueue(int s){ maxSize = s; priQueArray = new int[maxSize]; nItems = 0; } public void push(int value){ if(nItems==0){ priQueArray[0] =value; }else{ int j ; j = nItems-1; while(j>=0&& value>priQueArray[j]){ priQueArray[j+1] = priQueArray[j]; j--; } priQueArray[j+1] = value; } nItems++; } public int poll(){ int returnValue =priQueArray[nItems-1]; priQueArray[nItems-1] = -1; nItems--; return returnValue; } public static void main(String[] args) { PriorityQueue arrayQueue = new PriorityQueue(10); arrayQueue.push(12); arrayQueue.push(13); arrayQueue.push(14); System.out.println(arrayQueue.poll()); System.out.println(arrayQueue.poll()); arrayQueue.push(34); arrayQueue.push(56); arrayQueue.push(6756); arrayQueue.push(2342); System.out.println(arrayQueue.poll()); System.out.println(arrayQueue.poll()); System.out.println(arrayQueue.poll()); System.out.println(arrayQueue.poll()); System.out.println(arrayQueue.poll()); } }