目錄
一.數組(Array):
1.1? 特點:
1.2? 基本操作:
1.3? 使用數組的好處包括:
1.4? 數組也有一些限制:
二.集合框架(Collections Framework):
2.1? 列表(List):
2.1.1? 數組列表(ArrayList):
擴展知識:
方法:
ArrayList的遍歷方式
ArrayList使用泛型
Arrays工具類
2.1.2? 鏈表(LinkedList):
常用方法:
2.1.3? 使用選擇:
2.1.4??示例代碼:
2.2? 集(Set):
2.2.1? 哈希集(HashSet):
基本類型對應的包裝類表如下:
HashSet的常用方法包括:
2.2.2? 樹集(TreeSet):
TreeSet的常用方法包括:
2.2.3? 使用選擇:
2.2.4??示例代碼:
2.3? 映射(Map):
2.3.1? 哈希映射(HashMap):
2.3.2? 樹映射(TreeMap):
2.3.3??使用選擇
2.3.4??示例代碼
三.棧(Stack)和隊列(Queue):
3.1方法
3.2示例代碼
四.樹(Tree):
4.1? 二叉樹(Binary Tree):
4.2二叉搜索樹(Binary Search Tree):
4.3??操作方法
4.4??樹的遍歷
4.4.1樹的遍歷包括兩種主要方式:
4.4.2? 樹的兩種基本遍歷方式:
4.5? 示例代碼
五.圖(Graph):
六.堆(Heap):
七.鏈表(LinkedList):
八.MAP:
Java 提供了多種數據結構來有效地組織和處理數據。以下是一些常見的 Java 數據結構:
一.數組(Array):
數組(Array)是一種線性數據結構,用于存儲固定大小的相同類型元素的連續序列,可以通過索引快速訪問和修改元素。。在 Java 中,數組可以包含基本類型(如 int、double、char 等)或引用類型(如對象、字符串等)的元素。
1.1? 特點:
- 元素類型必須相同,即數組是同一類型的項的集合。
- 長度固定,在創建數組時需要指定大小,后續無法改變。
- 內存中分配連續的空間,元素之間存儲緊密,通過索引快速訪問和修改元素。
1.2? 基本操作:
-
初始化:創建一個數組,并為其賦初值。
-
遍歷:使用循環遍歷數組中的每個元素。
-
打印:將數組中的元素依次輸出。
-
最大值:遍歷數組,通過比較找到數組中的最大值。
-
最大值下標:遍歷數組,記錄當前最大值的下標。
- 使用增強for循環(foreach):對于數組中的每個元素,可以使用增強for循環進行遍歷并執行相應的操作。
- 復制數組有三種方法:
- 遍歷原數組,逐個復制到新數組。
- 使用
方法進行數組復制。System.arraycopy()
- 使用數組的
clone()
方法復制數組。
- 線性查找::從數組的第一個元素開始逐個比較,直到找到目標元素或遍歷完整個數組。時間復雜度為O(n),其中n為數組長度。
- 二分查找:要求在已排序的數組中進行查找。首先確定數組的中間元素,將目標值與中間元素進行比較,若相等則返回該位置,若小于中間元素,則在左半部分繼續查找,若大于中間元素,則在右半部分繼續查找。重復以上步驟,直到找到目標值或查找范圍為空。時間復雜度為O(logn),其中n為數組長度。
- 選擇排序:每次遍歷找到當前范圍內的最小(或最大)元素,并將其放置在已排序的部分的末尾。通過不斷選擇最小(或最大)的元素,逐步完成整個數組的排序。注意,選擇排序的時間復雜度為O(n^2),其中n為數組的長度。雖然簡單易實現,但對于較大規模的數據可能效率較低。
以下的Java代碼示例,包含數組的初始化、遍歷、打印、最大值、最大值下標、使用增強for循環遍歷、復制數組以及線性查找、二分查找和選擇排序算法的實現。
import java.util.Arrays;public class myClass {public static void main(String[] args) {// 初始化數組int[] arr = {5, 3, 9, 1, 7};// 遍歷數組for (int i = 0; i < arr.length; i++) {System.out.print(arr[i] + " ");}System.out.println();// 打印數組System.out.println(Arrays.toString(arr));// 最大值int max = arr[0];for (int i = 1; i < arr.length; i++) {if (arr[i] > max) {max = arr[i];}}System.out.println("最大值:" + max);// 最大值下標int maxIndex = 0;for (int i = 1; i < arr.length; i++) {if (arr[i] > arr[maxIndex]) {maxIndex = i;}}System.out.println("最大值下標:" + maxIndex);// 使用增強for循環遍歷for (int num : arr) {System.out.print(num + " ");}System.out.println();// 復制數組方法一(遍歷原數組,逐個復制到新數組)int[] copyArr1 = new int[arr.length];for (int i = 0; i < arr.length; i++) {copyArr1[i] = arr[i];}// 復制數組方法二(使用System.arraycopy()方法)int[] copyArr2 = new int[arr.length];System.arraycopy(arr, 0, copyArr2, 0, arr.length);// 復制數組方法三(使用數組的clone()方法)int[] copyArr3 = arr.clone();System.out.println("復制后的數組:" + Arrays.toString(copyArr3));// 線性查找int target = 9;int linearSearchIndex = -1;for (int i = 0; i < arr.length; i++) {if (arr[i] == target) {linearSearchIndex = i;break;}}System.out.println("線性查找:" + (linearSearchIndex != -1 ? linearSearchIndex : "未找到"));// 二分查找(前提是數組必須有序)Arrays.sort(arr); // 先排序int binarySearchIndex = Arrays.binarySearch(arr, target);System.out.println("二分查找:" + (binarySearchIndex >= 0 ? binarySearchIndex : "未找到"));// 選擇排序selectionSort(arr);System.out.println("選擇排序后的數組:" + Arrays.toString(arr));}// 選擇排序算法實現public static void selectionSort(int[] arr) {int n = arr.length;for (int i = 0; i < n - 1; i++) {int minIndex = i;for (int j = i + 1; j < n; j++) {if (arr[j] < arr[minIndex]) {minIndex = j;}}if (minIndex != i) {int temp = arr[i];arr[i] = arr[minIndex];arr[minIndex] = temp;}}}
}
運行結果:
5 3 9 1 7
[5, 3, 9, 1, 7]
最大值:9
最大值下標:2
5 3 9 1 7
復制后的數組:[5, 3, 9, 1, 7]
線性查找:2
二分查找:4
選擇排序后的數組:[1, 3, 5, 7, 9]
1.3? 使用數組的好處包括:
- 快速隨機訪問:由于元素在內存中連續存儲,所以可以通過索引快速定位和訪問元素。
- 內存效率:數組在創建時需要指定長度,適用于已知固定數量的元素存儲場景,不需要額外的指針或鏈接信息。
- 數組操作簡單:Java 提供了一些便利的方法和屬性,使得數組的操作更加簡單和高效。
1.4? 數組也有一些限制:
- 長度固定:一旦創建,長度無法改變,需要事先確定好所需的元素個數。
- 內存浪費:如果數組長度過大或未充分利用,會造成內存浪費。
- 數據類型:數組只能存儲一種類型的數據;
- 插入和刪除困難:在數組中插入或刪除元素可能需要移動其他元素,開銷較大。
二.集合框架(Collections Framework):
提供了一系列接口和類,用于存儲和操作對象的集合。常用的集合類包括:
2.1? 列表(List):
有序、可重復的集合,例如 ArrayList、LinkedList。
2.1.1? 數組列表(ArrayList):
- ArrayList是基于數組實現的動態數組,內部通過數組來存儲元素。
- 它可以自動擴容以適應元素的增加
- 它支持隨機訪問元素,即可以通過索引快速訪問指定位置的元素。
- 數組列表適用于頻繁讀取和隨機訪問元素的場景,因為它內部使用數組存儲,可以根據索引直接計算出元素的內存地址。
- ArrayList實現了List接口,繼承了AbstractList類,并且還實現了RandomAccess(隨機訪問)、Cloneable(克隆)和Serializable(可序列化)這些接口。
- 與Vector不同,ArrayList不是線程安全的。因此,在單線程環境下建議使用ArrayList,在多線程環境下可以選擇Vector或CopyOnWriteArrayList。
擴展知識:
Vector是Java中的一個舊的類,它與ArrayList具有相似的用法,但在性能和使用上存在一些差異。雖然Vector是線程安全的,但在大多數情況下,推薦使用更現代的替代方案。
一個常見的替代方案是使用Collections工具類提供的synchronizedList方法,該方法可以將ArrayList轉換為線程安全的List。以下是示例代碼:
List<String> lst = new ArrayList<>();
// 往lst中添加元素List<String> synList = Collections.synchronizedList(lst);
通過將原始的ArrayList通過synchronizedList方法包裝,我們可以獲得一個在并發環境下安全使用的List。
需要注意的是,在大多數情況下,如果不需要線程安全的特性,推薦使用ArrayList而不是Vector,因為ArrayList在性能上通常更優。只有在確實需要線程安全時,才會考慮使用Vector或通過Collections工具類獲得線程安全的List。
方法:
Collection相關方法:
這些方法屬于Collection類的一部分,可以被List和Set等子類繼承并使用。以下是一些常見的Collection類方法:
- boolean add(E element):向集合中添加一個元素。
- boolean addAll(Collection<? extends E> collection):將一個集合中的所有元素添加到當前集合中。
- void clear():清空集合中的所有元素。
- boolean contains(Object object):判斷集合是否包含指定對象。
- boolean containsAll(Collection<?> collection):判斷集合是否包含給定集合中的所有元素。
- boolean isEmpty():判斷集合是否為空。
- Iterator<E> iterator():返回一個用于迭代集合元素的迭代器。
- boolean remove(Object object):從集合中移除指定的對象。
- boolean removeAll(Collection<?> collection):從集合中移除給定集合中的所有元素。
- boolean retainAll(Collection<?> collection):僅保留集合中在給定集合中出現的元素,移除其他元素。
- int size():返回集合中的元素個數。
- Object[] toArray():將集合轉化為數組。
- <T> T[] toArray(T[] array):將集合轉化為指定類型的數組。
List接口:
List是Collection接口的子接口,擁有Collection所有方法外,還有一些對索引操作的方法。
- void add(int index, E element):在索引index處插入元素element。
- boolean addAll(int index, Collection<? extends E> c):將集合c中的所有元素插入到索引index處。
- E remove(int index):移除并返回索引index處的元素。
- int indexOf(Object o):返回對象o在ArrayList中第一次出現的索引。
- int lastIndexOf(Object o):返回對象o在ArrayList中最后一次出現的索引。
- E set(int index, E element):將索引index處的元素替換為新的element對象,并返回被替換的舊元素。
- E get(int index):返回索引index處的元素。
- List<E> subList(int fromIndex, int toIndex):返回從索引fromIndex(包含)到索引toIndex(不包含)的子列表。
- void sort(Comparator<? super E> c):根據指定的Comparator對ArrayList中的元素進行排序。
- void replaceAll(UnaryOperator<E> operator):使用指定的計算規則operator重新設置ArrayList的所有元素。
- ListIterator<E> listIterator():返回一個ListIterator對象,該接口繼承了Iterator接口,在Iterator接口基礎上增加了以下方法,允許向前迭代并添加元素。
- bookean hasPrevious():返回迭代器關聯的集合是否還有上一個元素;
- E previous();:返回迭代器上一個元素;
- void add(E e);:在指定位置插入元素;
更多 API 方法可以查看:ArrayList
ArrayList的遍歷方式
- 使用for循環和索引:
for (int i = 0; i < arrayList.size(); i++) {E element = arrayList.get(i);// 處理元素 }
- 使用for-each循環:
for (E element : arrayList) {// 處理元素 }
- 使用迭代器(Iterator)進行遍歷:
Iterator<E> iterator = arrayList.iterator(); while (iterator.hasNext()) {E element = iterator.next();// 處理元素 }
ArrayList<E>使用泛型
泛型數據類型,用于設置 objectName(對象名) 的數據類型,只能為引用數據類型。
對于ArrayList的泛型使用,可以通過在定義ArrayList時指定泛型類型來確保集合中只能存儲指定類型的元素。例如:
ArrayList<String> stringList = new ArrayList<>();
stringList.add("Hello");
stringList.add("World");
// 只能添加String類型的元素String element = stringList.get(0);
System.out.println(element); // 輸出: Hello
通過使用泛型,可以提供類型安全,并且在編譯期間就能夠捕獲類型不匹配的錯誤。?
Arrays工具類
Arrays工具類是Java提供的用于操作數組的工具類,以下是一些常用的方法:
- boolean equals(a, b):比較兩個數組是否相等。
- void fill(array, value):將指定的值填充到數組中的所有元素。
- void sort(array):對數組進行排序。
- int binarySearch(array, key):在已排序的數組中使用二分查找來查找指定的元素。
- void arraycopy(src, srcPos, dest, destPos, length):將源數組中的某個范圍的元素復制到目標數組的指定位置。
2.1.2? 鏈表(LinkedList):
- LinkedList是基于鏈表實現的雙向鏈表,內部通過節點(Node)來存儲元素并連接起來。
- 節點中包含了當前元素的值,以及指向前一個節點和后一個節點的引用。
- 鏈表支持快速插入和刪除操作,因為只需要修改節點的引用關系即可,不涉及移動其他元素。
- 鏈表適用于頻繁插入和刪除元素的場景,因為在鏈表中插入和刪除元素的開銷相對較小。
- 由于鏈表的存儲方式不同于數組,因此在訪問某個位置的元素時需要遍歷鏈表,因此隨機訪問的效率較低。
常用方法:
- void addFirst(E element):在鏈表的開頭插入元素。
- void addLast(E element):在鏈表的末尾插入元素。
- E getFirst():獲取鏈表中的第一個元素。
- E getLast():獲取鏈表中的最后一個元素。
- E removeFirst():移除并返回鏈表中的第一個元素。
- E removeLast():移除并返回鏈表中的最后一個元素。
- boolean contains(Object element):判斷鏈表是否包含指定元素。
- int size():返回鏈表中的元素個數。
- void clear():清空鏈表中的所有元素。
更多 API 方法可以查看:LinkedList
2.1.3? 使用選擇:
根據具體需求,選擇ArrayList還是LinkedList有以下一些考慮因素:
- 如果需要頻繁讀取和隨機訪問元素,可以選擇ArrayList。
- 如果需要頻繁插入和刪除元素,尤其是在列表的中間位置,可以選擇LinkedList。
- 如果對內存空間的利用比較敏感,LinkedList可能會占用更多的內存,而ArrayList使用的內存通常較為緊湊。
總的來說,ArrayList適用于讀取和隨機訪問操作更多的場景,而LinkedList適用于插入和刪除操作更頻繁的場景。
2.1.4??示例代碼:
下面一個簡單的示例代碼,展示了如何使用ArrayList和LinkedList進行基本操作:
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;public class ListExample {public static void main(String[] args) {// 使用ArrayListList<String> arrayList = new ArrayList<>();// 添加元素arrayList.add("Apple");arrayList.add("Banana");arrayList.add("Orange");// 獲取元素String firstElement = arrayList.get(0);System.out.println("ArrayList中第一個元素:" + firstElement);// 遍歷元素System.out.println("ArrayList的元素:");for (String element : arrayList) {System.out.println(element);}// 刪除元素arrayList.remove("Banana");// 使用LinkedListList<Integer> linkedList = new LinkedList<>();// 添加元素linkedList.add(10);linkedList.add(20);linkedList.add(30);// 獲取元素int lastElement = linkedList.get(linkedList.size() - 1);System.out.println("LinkedList中最后一個元素:" + lastElement);// 遍歷元素System.out.println("LinkedList的元素:");for (int element : linkedList) {System.out.println(element);}// 刪除元素linkedList.remove(0);}
}
運行結果:
ArrayList中第一個元素:Apple
ArrayList的元素:
Apple
Banana
Orange
LinkedList中最后一個元素:30
LinkedList的元素:
10
20
30
2.2? 集(Set):
集是一種無序的集合,不允許重復元素,例如 HashSet、TreeSet。
2.2.1? 哈希集(HashSet):
- HashSet是基于哈希表實現的集合,具有快速查找性能。
- 哈希集不保證元素的順序,且不允許重復元素。如果試圖插入重復元素,插入操作將被忽略。
- 它還繼承了Set接口和Collection接口的其他方法
- HashSet允許存儲null元素。
- 添加、刪除和查找元素的平均時間復雜度為O(1)。
HashSet 中的元素實際上是對象,一些常見的基本類型可以使用它的包裝類。
基本類型對應的包裝類表如下:
基本類型 | 引用類型 |
---|---|
boolean | Boolean |
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
HashSet的常用方法包括:
- boolean add(E element):向集合中添加指定元素,如果元素已經存在,則返回false。
- boolean remove(Object element):從集合中移除指定元素,如果元素存在并成功移除,則返回true。
- boolean contains(Object element):檢查集合中是否包含指定元素,如果包含則返回true。
- int size():返回集合中元素的數量。
- void clear():清空集合中的所有元素。?
更多 API 方法可以查看:HashSet?
2.2.2? 樹集(TreeSet):
- TreeSet是基于紅黑樹(自平衡二叉搜索樹)實現的有序集合。
- 樹集中的元素按照自然順序或自定義比較器進行排序,默認情況下按照元素的自然排序方式進行排序。
- 它還繼承了Set接口和Collection接口的其他方法
- 樹集不允許插入null元素。
- 插入、刪除和查找元素的時間復雜度為O(log N),其中N為樹集中的元素個數。
TreeSet的常用方法包括:
- boolean add(E element):向集合中添加指定元素,如果元素已經存在,則返回false。
- boolean remove(Object element):從集合中移除指定元素,如果元素存在并成功移除,則返回true。
- boolean contains(Object element):檢查集合中是否包含指定元素,如果包含則返回true。
- int size():返回集合中元素的數量。
- void clear():清空集合中的所有元素。
- E first():返回集合中的第一個(最小)元素。
- E last():返回集合中的最后一個(最大)元素。
- Iterator<E> iterator():返回在此集合上進行迭代的迭代器。
2.2.3? 使用選擇:
- 使用HashSet時,你可以快速添加、刪除和查找元素,并且元素的順序可能不同。
- 如果你希望元素有一定的順序,你可以使用TreeSet,它會根據元素的排序規則保持元素的有序性。
2.2.4??示例代碼:
下面一個簡單的示例代碼,展示了如何使用HashSet和TreeSet進行基本操作:
import java.util.HashSet;// 引入 HashSet 類
import java.util.TreeSet;// 引入 TreeSet 類public class myClass {public static void main(String[] args) {// 使用HashSetHashSet<String> hashSet = new HashSet<>();// 添加元素hashSet.add("Apple");hashSet.add("Banana");hashSet.add("Orange");hashSet.add("Grape");// 輸出集合中的元素System.out.println("HashSet:");for (String fruit : hashSet) {System.out.println(fruit);}// 檢查元素是否存在System.out.println("HashSet contains 'Apple': " + hashSet.contains("Apple")); // true// 刪除元素hashSet.remove("Orange");// 輸出修改后的集合System.out.println("HashSet after removal:");for (String fruit : hashSet) {System.out.println(fruit);}// 使用TreeSetTreeSet<Integer> treeSet = new TreeSet<>();// 添加元素treeSet.add(5);treeSet.add(10);treeSet.add(3);treeSet.add(8);// 輸出集合中的元素System.out.println("TreeSet:");for (int num : treeSet) {System.out.println(num);}// 獲取最小元素和最大元素System.out.println("Min element: " + treeSet.first()); // 3System.out.println("Max element: " + treeSet.last()); // 10}
}
運行結果:
HashSet:
Apple
Grape
Orange
Banana
HashSet contains 'Apple': true
HashSet after removal:
Apple
Grape
Banana
TreeSet:
3
5
8
10
Min element: 3
Max element: 10
2.3? 映射(Map):
由鍵值對組成的集合,每個鍵唯一,例如 HashMap、TreeMap。
2.3.1? 哈希映射(HashMap):
- 它是基于哈希表實現的映射結構。
- HashMap是一個散列表,它存儲的內容是鍵值對(key-value)映射。
- HashMap使用鍵的哈希碼來確定存儲位置,實現了 Map 接口,通過鍵快速查找值。
- 它具有較快的插入和查找操作,但不保證元素的順序。
常用方法:
- put(key, value): 將鍵值對插入到哈希映射中。
- get(key): 根據鍵獲取對應的值。
- containsKey(key): 檢查哈希映射中是否包含指定的鍵。
- remove(key): 移除哈希映射中指定鍵的鍵值對。
- size(): 返回哈希映射中鍵值對的數量。
更多 API 方法可以查看:HashMap
2.3.2? 樹映射(TreeMap):
- 它是基于紅黑樹實現的有序映射結構。
- TreeMap將鍵按照自然順序或通過自定義的比較器進行排序,并在內部維護一個有序的鍵值對集合。因此,可以根據鍵的順序快速檢索、遍歷和范圍查找元素。
常用方法:
- put(key, value): 將鍵值對插入到樹映射中。
- get(key): 根據鍵獲取對應的值。
- containsKey(key): 檢查樹映射中是否包含指定的鍵。
- remove(key): 移除樹映射中指定鍵的鍵值對。
- size(): 返回樹映射中鍵值對的數量。
- firstKey(): 返回樹映射中最小的鍵。
- lastKey(): 返回樹映射中最大的鍵。
- subMap(fromKey, toKey): 返回樹映射中鍵的一個子集,范圍從 fromKey(包括)到 toKey(不包括)。
除了上述方法,哈希映射和樹映射還提供了其他一些類似的方法,如獲取所有鍵的集合、清空映射等。具體的方法使用可以參考Java的官方文檔或相關教程。
2.3.3??使用選擇
這兩種映射都是非常常用的數據結構,在不同的場景下使用。
- HashMap適用于需要快速查找和插入元素的情況,并且不關心元素的順序。
- TreeMap適用于需要有序性的場景,可以按照鍵的順序進行操作和遍歷,在維護有序性的同時支持各種基本操作。
2.3.4??示例代碼
下面一個簡單的示例代碼,展示了如何使用HashMap和TreeMap進行基本操作:
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;public class myClass {public static void main(String[] args) {// 使用HashMapMap<String, Integer> hashMap = new HashMap<>();// 添加鍵值對到HashMaphashMap.put("Apple", 1);hashMap.put("Banana", 2);hashMap.put("Orange", 3);// 獲取指定鍵的值int appleValue = hashMap.get("Apple");System.out.println("Apple的值為:" + appleValue);// 檢查HashMap是否包含指定鍵boolean containsKey = hashMap.containsKey("Banana");System.out.println("HashMap是否包含Banana:" + containsKey);// 移除指定鍵的鍵值對hashMap.remove("Orange");// 遍歷HashMap的鍵值對for (String key : hashMap.keySet()) {int value = hashMap.get(key);System.out.println("鍵:" + key + ",值:" + value);}System.out.println("----------------------");// 使用TreeMapMap<String, Integer> treeMap = new TreeMap<>();// 添加鍵值對到TreeMaptreeMap.put("Apple", 1);treeMap.put("Banana", 2);treeMap.put("Orange", 3);// 獲取最小的鍵String firstKey = ((TreeMap<String, Integer>) treeMap).firstKey();System.out.println("最小的鍵:" + firstKey);// 獲取最大的鍵String lastKey = ((TreeMap<String, Integer>) treeMap).lastKey();System.out.println("最大的鍵:" + lastKey);// 遍歷TreeMap的鍵值對for (String key : treeMap.keySet()) {int value = treeMap.get(key);System.out.println("鍵:" + key + ",值:" + value);}}
}
運行結果:
Apple的值為:1
HashMap是否包含Banana:true
鍵:Apple,值:1
鍵:Banana,值:2
----------------------
最小的鍵:Apple
最大的鍵:Orange
鍵:Apple,值:1
鍵:Banana,值:2
鍵:Orange,值:3
三.棧(Stack)和隊列(Queue):
棧是一種后進先出(LIFO)的數據結構,常用操作有入棧和出棧;隊列是一種先進先出(FIFO)的數據結構,常用操作有入隊和出隊。Java 提供了 Stack 類和 Queue 接口,并有相關實現類如 LinkedList。
- 棧(Stack):是一種后進先出(LIFO)的數據結構,只允許在棧頂進行插入(入棧)和刪除(出棧)操作。相當于把元素放在一個類似于豎起的桶中,每次插入和刪除只能在桶的頂部進行。
- 隊列(Queue):是一種先進先出(FIFO)的數據結構,從隊尾插入元素(入隊),從隊頭刪除元素(出隊)。可以理解為排隊,先進來的人先出去。
在Java中,可以使用Stack類表示棧,它是Vector的子類。而Queue接口是Java集合框架的一部分,它定義了隊列的基本操作,如入隊、出隊、獲取隊頭元素等。Java提供了多個Queue接口的實現類,其中常用的是LinkedList,它既實現了List接口,又實現了Deque接口,可以作為隊列或雙端隊列使用。
3.1方法
Stack的常用方法包括:
- push(element):將元素壓入棧頂。
- pop():彈出并返回棧頂的元素。
- peek():返回棧頂的元素,但不會將其從棧中移除。
- isEmpty():判斷棧是否為空。
- size():返回棧中元素的個數。
Queue的常用方法包括:
- add(element):將元素添加到隊尾。
- offer(element):將元素添加到隊尾,并返回是否成功。
- remove():移除并返回隊頭的元素。
- poll():移除并返回隊頭的元素,如果隊列為空則返回null。
- peek():返回隊頭的元素,但不會將其從隊列中移除。
- element():返回隊頭的元素,如果隊列為空則拋出異常。
- isEmpty():判斷隊列是否為空。
- size():返回隊列中元素的個數。
3.2示例代碼
下面一個簡單的示例代碼,展示了如何使用Stack和Queue進行基本操作:
import java.util.Stack;
import java.util.LinkedList;
import java.util.Queue;public class myClass {public static void main(String[] args) {// 使用StackStack<Integer> stack = new Stack<>();// 入棧操作stack.push(1);stack.push(2);stack.push(3);// 出棧操作int poppedElement = stack.pop();System.out.println("出棧元素:" + poppedElement);// 獲取棧頂元素int topElement = stack.peek();System.out.println("棧頂元素:" + topElement);// 判斷棧是否為空boolean empty = stack.isEmpty();System.out.println("棧是否為空:" + empty);System.out.println("----------------------");// 使用QueueQueue<String> queue = new LinkedList<>();// 入隊操作queue.offer("Apple");queue.offer("Banana");queue.offer("Orange");// 出隊操作String polledElement = queue.poll();System.out.println("出隊元素:" + polledElement);// 獲取隊頭元素String peekedElement = queue.peek();System.out.println("隊頭元素:" + peekedElement);// 判斷隊列是否為空boolean emptyQueue = queue.isEmpty();System.out.println("隊列是否為空:" + emptyQueue);}
}
運行結果:
出棧元素:3
棧頂元素:2
棧是否為空:false
----------------------
出隊元素:Apple
隊頭元素:Banana
隊列是否為空:false
四.樹(Tree):
樹是一種非線性的數據結構,由節點和邊組成,用于表示具有層級關系的數據結構。常見的樹結構包括二叉樹、平衡樹、紅黑樹等。Java 提供了 TreeSet 和 TreeMap 來實現樹結構。
4.1? 二叉樹(Binary Tree):
是一種特殊的樹結構,每個節點最多有兩個子節點:左子節點和右子節點。一個節點可以沒有子節點,也可以只有一個子節點。
4.2二叉搜索樹(Binary Search Tree):
也稱為二叉查找樹或排序二叉樹,是一種特殊的二叉樹。它具有以下性質:
- 對于任意節點,其左子樹上的所有節點的值都小于該節點的值。
- 對于任意節點,其右子樹上的所有節點的值都大于該節點的值。
- 左子樹和右子樹都必須是二叉搜索樹。
由于二叉搜索樹的性質,我們可以利用它來高效地進行查找、插入和刪除操作。對于任意節點,其左子樹的節點值都小于該節點,因此在查找、插入或刪除時,可以通過比較節點的值,有選擇性地在左子樹或右子樹中進行操作,從而提高效率。
Java中可以使用TreeSet和TreeMap來實現二叉搜索樹。它們基于紅黑樹(Red-Black Tree)實現,紅黑樹是一種自平衡的二叉搜索樹,保持了良好的平衡性能。
- TreeSet是一個基于紅黑樹實現的有序集合,它存儲的元素按照自然順序或者指定的比較器進行排序,并且不允許出現重復元素。
- TreeMap是一個基于紅黑樹實現的有序映射,它存儲鍵值對,并按照鍵的自然順序或者指定的比較器進行排序。與TreeSet類似,TreeMap也不允許出現重復的鍵。
通過使用TreeSet和TreeMap,我們可以方便地操作二叉搜索樹的相關操作,如插入、刪除、查找等,并保持元素的有序性。
4.3??操作方法
- 創建樹IntTree(&T):創建1個空樹T。
- 銷毀樹DestroyTree(&T)
- 構造樹CreatTree(&T,deinition)
- 置空樹ClearTree(&T):將樹T置為空樹。
- 判空樹TreeEmpty(T)
- 求樹的深度TreeDepth(T)
- 獲得樹根Root(T)
- 獲取結點Value(T,cur_e,&e):將樹中結點cur_e存入e單元中。
- 數據賦值Assign(T,cur_e,value):將結點value,賦值于樹T的結點cur_e中。
- 獲得雙親Parent(T,cur_e):返回樹T中結點cur_e的雙親結點。
- 獲得最左孩子LeftChild(T,cur_e):返回樹T中結點cur_e的最左孩子。
- 獲得右兄弟RightSibling(T,cur_e):返回樹T中結點cur_e的右兄弟。
- 插入子樹InsertChild(&T,&p,i,c):將樹c插入到樹T中p指向結點的第i個子樹之前。
- 刪除子樹DeleteChild(&T,&p,i):刪除樹T中p指向結點的第i個子樹。
- 遍歷樹TraverseTree(T,visit())
4.4??樹的遍歷
4.4.1樹的遍歷包括兩種主要方式:
-
深度優先遍歷(DFS):
- 先序遍歷(Preorder):根節點 -> 左子樹 -> 右子樹
- 中序遍歷(Inorder):左子樹 -> 根節點 -> 右子樹
- 后序遍歷(Postorder):左子樹 -> 右子樹 -> 根節點
-
廣度優先遍歷(BFS): 從根節點開始,按層級順序逐層遍歷樹的節點,從左到右依次訪問每個節點。
無論是深度優先遍歷還是廣度優先遍歷,都有各自的應用場景。可以根據具體需求選擇適合的遍歷方式來處理樹中的節點。
4.4.2? 樹的兩種基本遍歷方式:
- 先序遍歷(Preorder traversal):
- 訪問根節點。
- 遞歸地對左子樹進行先序遍歷。
- 遞歸地對右子樹進行先序遍歷。
先序遍歷的順序是先訪問根節點,然后按照從左到右的順序依次訪問左子樹和右子樹。
- 中序遍歷(Inorder traversal):
- 遞歸地對左子樹進行中序遍歷。
- 訪問根節點。
- 遞歸地對右子樹進行中序遍歷。
中序遍歷的順序是先按照從左到右的順序遞歸訪問左子樹,然后訪問根節點,最后按照從左到右的順序遞歸訪問右子樹。
這兩種遍歷方法都是通過遞歸實現的,可以用來遍歷二叉樹或其他類型的樹結構。它們在不同的情況下有各自的應用,具體取決于問題的需求。
4.5? 示例代碼
下面一個簡單的示例代碼,展示了如何使用Binary Tree和Binary Search Tree進行基本操作:
// 定義二叉樹節點類
class TreeNode {int val;TreeNode left;TreeNode right;public TreeNode(int val) {this.val = val;this.left = null;this.right = null;}
}// 二叉樹類
class BinaryTree {TreeNode root;public BinaryTree() {root = null;}// 插入節點public void insert(int val) {root = insertNode(root, val);}private TreeNode insertNode(TreeNode node, int val) {if (node == null) {return new TreeNode(val);}// 如果值小于當前節點,則插入左子樹if (val < node.val) {node.left = insertNode(node.left, val);}// 如果值大于等于當前節點,則插入右子樹else {node.right = insertNode(node.right, val);}return node;}// 先序遍歷public void preOrderTraversal() {preOrder(root);}private void preOrder(TreeNode node) {if (node == null) {return;}System.out.print(node.val + " ");preOrder(node.left);preOrder(node.right);}
}// 二叉搜索樹類
class BinarySearchTree {TreeNode root;public BinarySearchTree() {root = null;}// 插入節點public void insert(int val) {root = insertNode(root, val);}private TreeNode insertNode(TreeNode node, int val) {if (node == null) {return new TreeNode(val);}// 如果值小于當前節點,則插入左子樹if (val < node.val) {node.left = insertNode(node.left, val);}// 如果值大于等于當前節點,則插入右子樹else {node.right = insertNode(node.right, val);}return node;}// 中序遍歷public void inOrderTraversal() {inOrder(root);}private void inOrder(TreeNode node) {if (node == null) {return;}inOrder(node.left);System.out.print(node.val + " ");inOrder(node.right);}
}// 測試代碼
public class myClass {public static void main(String[] args) {// 創建二叉樹,并插入節點BinaryTree binaryTree = new BinaryTree();binaryTree.insert(5);binaryTree.insert(3);binaryTree.insert(7);binaryTree.insert(2);binaryTree.insert(4);binaryTree.insert(6);binaryTree.insert(8);// 先序遍歷二叉樹System.out.print("二叉樹 -先序遍歷: ");binaryTree.preOrderTraversal();System.out.println();// 創建二叉搜索樹,并插入節點BinarySearchTree binarySearchTree = new BinarySearchTree();binarySearchTree.insert(5);binarySearchTree.insert(3);binarySearchTree.insert(7);binarySearchTree.insert(2);binarySearchTree.insert(4);binarySearchTree.insert(6);binarySearchTree.insert(8);// 中序遍歷二叉搜索樹System.out.print("二叉搜索樹 - 中序遍歷: ");binarySearchTree.inOrderTraversal();System.out.println();}
}
運行結果:
二叉樹 -先序遍歷: 5 3 2 4 7 6 8
二叉搜索樹 - 中序遍歷: 2 3 4 5 6 7 8
五.圖(Graph):
圖(Graph)是由節點(Vertex)和邊(Edge)組成的一種非線性數據結構,用于表示對象之間的關聯關系。可以將節點視為圖中的元素,并且節點可以與其他節點通過邊相連接。
在實際應用中,圖可用于解決各種問題,如社交網絡分析、路徑搜索、最短路徑算法等。在 Java 中,可以自行實現圖的數據結構和相關算法,或使用第三方庫(如JGraphT、Java Universal Network/Graph Framework等)來操作和處理圖結構。
- 有向圖(Directed Graph):也稱為有向圖、定向圖或有向網絡。有向圖中的邊具有方向性,表示節點之間的單向關系。如果節點 A 到節點 B 之間存在一條有向邊,那么從節點 A 出發可以到達節點 B,但反過來不行。
- 無向圖(Undirected Graph):也稱為無向圖、非定向圖或無向網絡。無向圖中的邊沒有方向,表示節點之間的雙向關系。如果節點 A 和節點 B 之間有一條邊相連,則可以從節點 A 到節點 B 或者從節點 B 到節點 A。
六.堆(Heap):
堆是一種特殊的樹形數據結構,滿足堆屬性。用于有效地找到最大值或最小值的數據結構。Java 提供了優先級隊列(PriorityQueue)來實現堆。
- 最大堆(Max Heap):每個父節點的值都大于或等于其子節點的值。
- 最小堆(Min Heap):每個父節點的值都小于或等于其子節點的值。
七.鏈表(LinkedList):
鏈表是一種線性數據結構,也叫動態數據結構,但是并不會按線性的順序存儲數據,由節點和指針組成,每個節點包含數據和指向下一個節點的指針。
鏈表可分為單向鏈表和雙向鏈表。
一個單向鏈表包含兩個值: 當前節點的值和一個指向下一個節點的鏈接。
一個雙向鏈表有三個整數值: 數值、向后的節點鏈接、向前的節點鏈接。
八.MAP:
Map是一種用于存儲鍵值對的接口。它提供了一種將鍵映射到值的方式,可以通過鍵快速查找對應的值。在Map中,鍵是唯一的,每個鍵最多只能映射到一個值。常見的Map實現類包括HashMap、TreeMap、LinkedHashMap等。這些實現類提供了不同的性能特點和迭代順序,可以根據具體需求選擇適合的實現類。使用Map可以方便地進行數據檢索、插入、刪除和更新操作,非常適合處理需要快速查找的場景。