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 }