Java实现的基础数据结构
Java实现的基础数据结构
0,常用的基础数据结构
图1 基础数据结构&相关特性
图2 Java自带的类集框架&继承关系图
1,数组【Array】
特点:长度固定、查找方便【直接使用index查找即可】、增加、删除麻烦。
图3 数组【查找直接使用index指针即可直接查询】
图4 数组添加【需要重新创建新数组对象并产生垃圾空间】
图5 数组删除【需要重新创建新数组并且产生垃圾空间】
①创建实例化数组对象
1 public class Demo1_Array { 2 public static void main(String[] args) { 3 String [] array=new String[5];//需要初始化长度 4 array[0]="hello"; 5 array[1]="world"; 6 array[4]="Mufasa"; 7 // array[5]="right or not";//ArrayIndexOutOfBoundsException 8 for(String str:array){ 9 System.out.print(str+"、");//hello、world、null、null、Mufasa、 10 } 11 } 12 }
②对实例化数组进行扩容【利用Java反射机制】
1 public class Demo1_Array2 { 2 public static void main(String[] args) { 3 String [] array={"hello","world",null,null,"Mufasa"};//实例化&赋值 4 array = (String[])resizeArray(array,10); 5 for(String str:array){ 6 System.out.print(str+"、");//hello、world、null、null、Mufasa、 7 } 8 } 9 10 private static Object resizeArray(Object oldArray, int newSize) {//数组扩容!!!真麻烦,还利用反射机制来实现 11 int oldSize = java.lang.reflect.Array.getLength(oldArray);//获取旧数组长度,向上转型!!! 12 // int oldSize =oldArray.length;//无法在此使用,因为array内容的是不定类型 13 Class elementType = oldArray.getClass().getComponentType();//获取对象类别 14 Object newArray = java.lang.reflect.Array.newInstance(elementType,newSize);//利用Java的反射机制实例化新数组 15 int preserveLength = Math.min(oldSize, newSize);//判断是否需要copy数据 16 if (preserveLength > 0) 17 System.arraycopy(oldArray, 0, newArray, 0, preserveLength); 18 return newArray;//oldArray切断索引成为垃圾由Runtime.getRuntime().gc();回收处理 19 } 20 }
③数组删除与增添,本质上是创建新的数值并且copy数值【需要私有反射实例化新数组,这里需要进一步优化】
1 public class Demo1_Array4 { 2 public static void main(String[] args) { 3 String [] array=new String[5];//需要初始化长度 4 array[0]="hello"; 5 array[1]="world"; 6 array[4]="Mufasa"; 7 array=drop(array,3); 8 for(String str:array){ 9 System.out.print(str+"、");//hello、world、null、null、Mufasa、 10 } 11 12 } 13 public static String[] drop(Object[] oldArray,int index){//删除指定位置上的元素 14 int size= java.lang.reflect.Array.getLength(oldArray); 15 if(index<0 || index>size) { 16 throw new RuntimeException("删除索引范围有误"); 17 }else { 18 Class elementType = oldArray.getClass().getComponentType();//获取对象类别 19 Object newArray = java.lang.reflect.Array.newInstance(elementType,size-1); 20 String[] newStringArray=(String[])newArray; 21 int counter=0; 22 for(int i=0;i<oldArray.length;i++){ 23 if(i!=index){ 24 newStringArray[counter]= (String) oldArray[i]; 25 counter++; 26 }else { 27 continue; 28 } 29 } 30 return newStringArray; 31 } 32 } 33 }
④数组添加元素,本质也是创建新数组长度+1拷贝,index后移、赋值
1 public class Demo1_Array5 { 2 public static void main(String[] args) { 3 String [] array=new String[5];//需要初始化长度 4 array[0]="hello"; 5 array[1]="world"; 6 array[4]="Mufasa"; 7 array=add(array,3,"添加字符串"); 8 for(String str:array){ 9 System.out.print(str+"、");//hello、world、null、null、Mufasa、 10 } 11 12 } 13 public static String[] add(Object[] oldArray,int index,String str){//删除指定位置上的元素 14 int size= java.lang.reflect.Array.getLength(oldArray); 15 if(index<0 || index>size) { 16 throw new RuntimeException("添加索引范围有误"); 17 }else { 18 Class elementType = oldArray.getClass().getComponentType();//获取对象类别 19 Object newArray = java.lang.reflect.Array.newInstance(elementType,size+1); 20 String[] newStringArray=(String[])newArray; 21 int counter=0; 22 for(int i=0;i<oldArray.length;i++){ 23 if(i!=index){ 24 newStringArray[counter]= (String) oldArray[i]; 25 counter++; 26 }else { 27 newStringArray[counter]= (String) oldArray[i]; 28 counter++; 29 newStringArray[counter]=str; 30 counter++; 31 } 32 } 33 return newStringArray; 34 } 35 } 36 }
备注:当然也可以直接使用Java自带的类集框架中的ArrayList、Vector
1 import java.util.ArrayList; 2 import java.util.List; 3 4 public class Demo1_Array6 { 5 public static void main(String[] args) { 6 List<String> array=new ArrayList<>();//需要初始化长度 7 array.add("hello"); 8 array.add("world"); 9 // array.set(2,"Mufasa"); 10 array.add("扩容!"); 11 System.out.println(array.size()); 12 for(String str:array){ 13 System.out.print(str+"、");//hello、world、null、null、Mufasa、 14 } 15 } 16 }
Vector中方法使用sychronized修饰符,线程安全【与ArrayList的区别】;
2,链表【Linked List】
使用Node节点进行设计,功能:基本的setter、getter、add、getSize、remove等功能。
图6 链表
图7 链表增加【不用重新创建对象,不产生垃圾空间】
图8 链表删除【①断开②重新建立链接】
1 class Node{ 2 private String str=null; 3 private Node nextNode=null; 4 public Node(String str){ 5 this.str=str; 6 } 7 public void add(Node nextNode){//先遍历到最后一个再添加 8 Node indexNode=this.nextNode; 9 while(true){ 10 if(indexNode.hasNext()==false){ 11 break; 12 } 13 indexNode=indexNode.getNextNode(); 14 } 15 indexNode.setNextNode(nextNode); 16 } 17 /* 18 public void add(Node nextNode,int index){//方法重载,指定位点上添加元素 19 if(index==0){ 20 String str_mid=this.str; 21 this.str=nextNode.getStr(); 22 this.nextNode.setStr(str_mid); 23 this.nextNode.setNextNode(); 24 } 25 Node indexNode=this.nextNode; 26 int size=1; 27 while(true){ 28 if(indexNode.hasNext()==false || size==index){ 29 break; 30 } 31 size++;//放在后面0开始 32 indexNode=indexNode.getNextNode(); 33 System.out.println("size:"+size+",元素:"+indexNode.getStr()); 34 } 35 if(size<index){ 36 throw new RuntimeException("添加元素索引超出范围"); 37 }else { 38 nextNode.setNextNode(indexNode.getNextNode());//先在新节点后加入 39 indexNode.setNextNode(nextNode);//后在前面节点加入新节点 40 } 41 }*/ 42 43 public int getSize(){ 44 int size=0; 45 Node indexNode=this.nextNode; 46 while(true){ 47 size++; 48 if(indexNode.hasNext()==false){ 49 break; 50 } 51 indexNode=indexNode.getNextNode(); 52 } 53 return size; 54 } 55 public void setNextNode(Node nextNode) { 56 this.nextNode = nextNode; 57 } 58 59 public Node getNextNode() { 60 return this.nextNode; 61 } 62 63 public String getStr() { 64 return str; 65 } 66 public void setStr(String str){ 67 this.str=str; 68 } 69 public boolean hasNext(){ 70 if(nextNode!=null){ 71 return true; 72 }else { 73 return false; 74 } 75 } 76 } 77 78 public class Demo2_LinkedList { 79 public static void main(String[] args) { 80 String[] array={"begin","1","2","3","4","5"}; 81 Node rootNode=null; 82 Node indexNode=null; 83 boolean flag=true; 84 for(String str:array){ 85 if(flag){ 86 rootNode=new Node(str); 87 indexNode=rootNode; 88 flag=false; 89 }else { 90 indexNode.setNextNode(new Node(str)); 91 indexNode=indexNode.getNextNode(); 92 } 93 } 94 rootNode.add(new Node("添加元素"),2); 95 indexNode=rootNode; 96 // System.out.println(rootNode.getSize()); 97 while(true){ 98 System.out.println(indexNode.getStr()); 99 if(indexNode.hasNext()==false){ 100 break; 101 } 102 indexNode=indexNode.getNextNode(); 103 } 104 } 105 }
3,栈【Stack】
先进后出的一种数据结构,解决方法:①双向链表,略;②数组后续遍历;
使用Vector数组构建Stack
1 import java.util.List; 2 import java.util.Vector; 3 4 class Stack_m<T>{//使用泛型 5 private List<T> stack=new Vector<T>(); 6 public void push(T t){ 7 stack.add(t); 8 } 9 public T pop(){ 10 int size=stack.size(); 11 T mid; 12 mid=stack.get(size-1); 13 stack.remove(size-1); 14 return mid; 15 } 16 } 17 public class Demo3_Stack { 18 public static void main(String[] args) { 19 Stack_m stack_m=new Stack_m(); 20 stack_m.push("hello"); 21 stack_m.push("world"); 22 stack_m.push("Mufasa"); 23 stack_m.push("最后一个push"); 24 for(int i=0;i<4;i++){ 25 System.out.println(stack_m.pop()); 26 } 27 } 28 }
4,队列【Queue】
通用:先进先出,一端输入另一端输出;特殊:优先队列。
使用Vector实现通用队列
1 import java.util.List; 2 import java.util.Vector; 3 4 class Queue_m<T>{ 5 private List<T> stack=new Vector<T>(); 6 public void add(T t){ 7 stack.add(t); 8 } 9 public T offer(){ 10 int size=stack.size(); 11 T mid; 12 mid=stack.get(0); 13 stack.remove(0); 14 return mid; 15 } 16 } 17 public class Demo4_Queue { 18 public static void main(String[] args) { 19 Queue_m queue_m=new Queue_m(); 20 queue_m.add("hello"); 21 queue_m.add("world"); 22 queue_m.add("Mufasa"); 23 queue_m.add("最后一个push"); 24 for(int i=0;i<4;i++){ 25 System.out.println(queue_m.offer()); 26 } 27 } 28 }
使用Vector实现优先队列PriorityQueue【待:泛型这个还没处理好】
1 import java.util.List; 2 import java.util.Vector; 3 4 class Queue_m1<T>{ 5 private List<T> queue=new Vector<T>(); 6 public void add(T t){ 7 int index=0; 8 for(T temp:queue){ 9 } 10 queue.add(t); 11 } 12 public T offer(){ 13 int size=queue.size(); 14 T mid; 15 mid=queue.get(0); 16 queue.remove(0); 17 return mid; 18 } 19 // private boolean compareTo(T t1,T t2){//需要覆写compareTo 20 // if() 21 // return 22 // } 23 } 24 25 public class Demo4_PriorityQueue { 26 public static void main(String[] args) { 27 Queue_m queue_m=new Queue_m(); 28 queue_m.add("hello"); 29 queue_m.add("world"); 30 queue_m.add("Mufasa"); 31 queue_m.add("最后一个push"); 32 for(int i=0;i<4;i++){ 33 System.out.println(queue_m.offer()); 34 } 35 } 36 }
5,图【Graph】
图数据结构有两种表现形式:①邻接矩阵形式;②邻接表形式;
1 import java.util.LinkedList; 2 import java.util.Vector; 3 4 class Graph_m1{//有两种类型,类型1:邻接矩阵形式 5 private Vector<Vector<Integer>> graph=new Vector<Vector<Integer>>();//叠加Vector,【行】为Vector,【列】为元素 6 private Vector<Integer> midVector; 7 public Graph_m1(){} 8 public void add(Vector<Integer> midVector){//方法重载 9 this.graph.add(midVector); 10 } 11 public void add(int index1,Vector<Integer> midVector){//方法重载 12 this.graph.add(index1,midVector); 13 } 14 public void add(int index1, int t){//方法重载 15 midVector=graph.get(index1); 16 midVector.add(t); 17 graph.set(index1,midVector); 18 } 19 public void add(int index1, int index2, int t){//方法重载 20 midVector=graph.get(index1); 21 midVector.add(index2,t); 22 graph.set(index1,midVector); 23 } 24 public void set(int index1, int index2, int t){ 25 midVector=graph.get(index1); 26 midVector.set(index2,t); 27 graph.set(index1,midVector); 28 } 29 public int get(int index1,int index2){ 30 midVector=graph.get(index1); 31 return midVector.get(index2); 32 } 33 public void getAll(){ 34 for(Vector<Integer> temp:graph){ 35 for(Integer temp1:temp){ 36 System.out.print(temp1+","); 37 } 38 System.out.println(""); 39 } 40 } 41 } 42 class Graph_m2<T>{//形式2:邻接表形式 43 private LinkedList<LinkedList<T>> graph =new LinkedList<LinkedList<T>>(); 44 private LinkedList<T> midLinkedList; 45 //set,get,getAll方法 46 public void add(LinkedList<T> midLinkedList){ 47 this.graph.add(midLinkedList); 48 } 49 public void add(int index1,LinkedList<T> midLinkedList){ 50 this.graph.add(index1,midLinkedList); 51 } 52 53 public void getAll(){ 54 for(LinkedList<T> temp:this.graph){ 55 for(T temp1:temp){ 56 System.out.print(temp1+","); 57 } 58 System.out.println(); 59 } 60 } 61 } 62 public class Demo5_Graph { 63 public static void main(String[] args) { 64 Graph_m2 graph=new Graph_m2(); 65 LinkedList<Integer> linkedList; 66 for(int i=0;i<3;i++){ 67 linkedList=new LinkedList<Integer>(); 68 for(int j=0;j<5;j++){ 69 linkedList.add(j+i); 70 } 71 graph.add(linkedList); 72 } 73 graph.getAll(); 74 } 75 }
6,树【Tree】
可以简单理解为一种特殊的不包含圈的单向图【发散型】。具体有:普通树、二叉树【最常用】、堆【heap】、哈夫曼树。
这里暂时只考虑二叉树的结构。
图xx 二叉树
通用二叉树实现代码【使用Node】
1 class BinTree{ 2 private String str; 3 private BinTree leftTree; 4 private BinTree rightTree; 5 public BinTree(String str){ 6 this.str=str; 7 } 8 9 public void setStr(String str) { 10 this.str = str; 11 } 12 13 public void setLeftTree(BinTree leftTree) { 14 this.leftTree = leftTree; 15 } 16 17 public void setRightTree(BinTree rightTree) { 18 this.rightTree = rightTree; 19 } 20 21 public String getStr() { 22 return str; 23 } 24 25 public BinTree getLeftTree() { 26 return leftTree; 27 } 28 29 public BinTree getRightTree() { 30 return rightTree; 31 } 32 33 } 34 35 public class Demo6_Tree { 36 public static void main(String[] args) { 37 BinTree rootTree=new BinTree("a"); 38 rootTree.setLeftTree(new BinTree("b")); 39 rootTree.setRightTree(new BinTree("c")); 40 41 BinTree midTree=null; 42 midTree=rootTree.getLeftTree(); 43 midTree.setLeftTree(new BinTree("d")); 44 midTree.setRightTree(new BinTree("e")); 45 46 midTree=rootTree.getRightTree(); 47 midTree.setLeftTree(new BinTree("f")); 48 midTree.setRightTree(new BinTree("g")); 49 } 50 }
7,堆【Heap】
借用Java类集中的ArrayList实现Heap
1 import java.util.ArrayList; 2 3 class Heap_m{ 4 private ArrayList<Integer> arryList=new ArrayList<Integer>(); 5 private boolean type;//true表示最大堆,false表示最小堆 6 private Integer mid_i;//只是负责数据交换 7 public Heap_m(boolean type){ 8 this.type=type; 9 } 10 11 public void add(int i){ 12 arryList.add(i); 13 shiftUp(this.arryList.size()-1); 14 } 15 public int deletRoot(){//删除根节点并返回其值 16 int mid_root=this.arryList.get(0); 17 this.mid_i=this.arryList.get(this.arryList.size()-1); 18 this.arryList.remove(this.arryList.size()-1); 19 this.arryList.set(0,this.mid_i); 20 shiftDown(0); 21 return mid_root; 22 } 23 public int delet(int index){//删除指定index节点,并返回其值 24 if(index<0 || index>this.arryList.size()-1){ 25 throw new IndexOutOfBoundsException("删除节点index范围有误"); 26 } 27 int mid_value=this.arryList.get(index); 28 this.mid_i=this.arryList.get(this.arryList.size()-1); 29 this.arryList.remove(this.arryList.size()-1); 30 this.arryList.set(index,this.mid_i); 31 shiftDown(index); 32 return mid_value; 33 } 34 35 private void shiftUp(int index){//添加数据的时候进行操作 36 if(type){//最大堆 37 if((index-1)/2!=-1){ 38 if(this.arryList.get((index - 1) / 2) <this.arryList.get(index)){ 39 mid_i=this.arryList.get((index - 1) / 2); 40 this.arryList.set((index - 1) / 2,this.arryList.get(index)); 41 this.arryList.set(index,mid_i); 42 shiftUp((index - 1) / 2);//递归调用 43 } 44 } 45 }else {//最小堆 46 if((index-1)/2!=-1){ 47 if(this.arryList.get((index - 1) / 2) >this.arryList.get(index)){ 48 mid_i=this.arryList.get((index - 1) / 2); 49 this.arryList.set((index - 1) / 2,this.arryList.get(index)); 50 this.arryList.set(index,mid_i); 51 shiftUp((index - 1) / 2);//递归调用 52 } 53 } 54 } 55 } 56 57 private void shiftDown(int index){//删除数据的时候进行操作 58 if(type){//最大堆 59 if(index*2+1 < this.arryList.size()){ 60 if(this.arryList.get(2*index+1) >this.arryList.get(index)){ 61 mid_i=this.arryList.get(2*index+1); 62 this.arryList.set(2*index+1,this.arryList.get(index)); 63 this.arryList.set(index,mid_i); 64 shiftDown(2*index+1);//递归调用 65 } 66 } 67 }else {//最小堆 68 if(index*2+1 < this.arryList.size()){ 69 if(this.arryList.get(2*index+1) <this.arryList.get(index)){ 70 mid_i=this.arryList.get(2*index+1); 71 this.arryList.set(2*index+1,this.arryList.get(index)); 72 this.arryList.set(index,mid_i); 73 shiftDown(2*index+1);//递归调用 74 } 75 } 76 } 77 } 78 79 public ArrayList<Integer> getHeap_m() { 80 return this.arryList; 81 } 82 } 83 public class Demo7_Heap { 84 public static void main(String[] args) { 85 // Heap_m heap_m=new Heap_m(true); 86 Heap_m heap_m=new Heap_m(false); 87 heap_m.add(5); 88 heap_m.add(10); 89 heap_m.add(1); 90 heap_m.add(7); 91 heap_m.add(2); 92 System.out.println(heap_m.getHeap_m()); 93 System.out.println(heap_m.deletRoot()); 94 System.out.println(heap_m.getHeap_m()); 95 heap_m.delet(-1); 96 } 97 }
8,散列表【Hash】
特点:仅支持插入、查找、删除
拉链型HashTable
1 class HashTable_linked{//拉链型hashtable 2 private Node[] values; 3 private int j; 4 public HashTable_linked(){//默认16长度,2的冥次方 5 this.values=new Node[16]; 6 } 7 public HashTable_linked(int length){//手动设置数据槽容量 8 this.values=new Node[length]; 9 } 10 public void insert(int key,String value){ 11 this.j=hashCode(key); 12 if(this.values[j]==null){//为空就添加root节点 13 this.values[j]=new Node(value); 14 }else { 15 this.values[j].add(new Node(value)); 16 } 17 } 18 public Object search(int key){//通过key搜索某个元素 19 this.j=hashCode(key); 20 if(this.values[this.j]!=null){ 21 return this.values[this.j]; 22 }else{ 23 return null; 24 } 25 } 26 private int hashCode(int key){//除余法散列函数h(k)=k%m 27 return key%this.values.length; 28 } 29 } 30 31 public class Demo8_HashTable { 32 public static void main(String[] args) {//拉链型HashTable 33 HashTable_linked hashTable=new HashTable_linked(10); 34 hashTable.insert(11,"你好"); 35 hashTable.insert(39,"世界"); 36 hashTable.insert(22,"权利的游戏"); 37 hashTable.insert(211,"努力奋斗"); 38 hashTable.insert(211,"努力奋斗+1"); 39 Node node=(Node)hashTable.search(211); 40 System.out.println(node.getStr()); 41 System.out.println(node.getNextNode().getStr()); 42 System.out.println(node.getNextNode().getNextNode().getStr()); 43 } 44 }
链表Node数据结构:
1 class Node{ 2 private String str=null; 3 private Node nextNode=null; 4 public Node(String str){ 5 this.str=str; 6 } 7 public void add(Node nextNode){//先遍历到最后一个再添加 8 Node indexNode=this;//当前对象 9 while(true){ 10 if(indexNode.hasNext()==false){ 11 break; 12 } 13 indexNode=indexNode.getNextNode(); 14 } 15 indexNode.setNextNode(nextNode); 16 } 17 /* 18 public void add(Node nextNode,int index){//方法重载,指定位点上添加元素 19 if(index==0){ 20 String str_mid=this.str; 21 this.str=nextNode.getStr(); 22 this.nextNode.setStr(str_mid); 23 this.nextNode.setNextNode(); 24 } 25 Node indexNode=this.nextNode; 26 int size=1; 27 while(true){ 28 if(indexNode.hasNext()==false || size==index){ 29 break; 30 } 31 size++;//放在后面0开始 32 indexNode=indexNode.getNextNode(); 33 System.out.println("size:"+size+",元素:"+indexNode.getStr()); 34 } 35 if(size<index){ 36 throw new RuntimeException("添加元素索引超出范围"); 37 }else { 38 nextNode.setNextNode(indexNode.getNextNode());//先在新节点后加入 39 indexNode.setNextNode(nextNode);//后在前面节点加入新节点 40 } 41 }*/ 42 43 public int getSize(){ 44 int size=0; 45 Node indexNode=this.nextNode; 46 while(true){ 47 size++; 48 if(indexNode.hasNext()==false){ 49 break; 50 } 51 indexNode=indexNode.getNextNode(); 52 } 53 return size; 54 } 55 public void setNextNode(Node nextNode) { 56 this.nextNode = nextNode; 57 } 58 59 public Node getNextNode() { 60 return this.nextNode; 61 } 62 63 public String getStr() { 64 return str; 65 } 66 public void setStr(String str){ 67 this.str=str; 68 } 69 public boolean hasNext(){ 70 if(nextNode!=null){ 71 return true; 72 }else { 73 return false; 74 } 75 } 76 }