Java實(shí)現(xiàn)堆算法的使用示例
堆是一種特殊的數(shù)據(jù)結(jié)構(gòu),它是一棵完全二叉樹(shù),且滿(mǎn)足堆的性質(zhì):對(duì)于每個(gè)節(jié)點(diǎn),它的值都不小于(或不大于)它的孩子節(jié)點(diǎn)的值。根節(jié)點(diǎn)的值就是堆中的最大值(或最小值)。
Java中提供了一個(gè)Heap類(lèi),可以用來(lái)實(shí)現(xiàn)堆的操作。Heap類(lèi)是一個(gè)抽象類(lèi),它定義了堆的基本操作方法,如插入、刪除、獲取最大(或最?。┲档?。
要使用Heap類(lèi),需要?jiǎng)?chuàng)建一個(gè)具體的實(shí)現(xiàn)類(lèi),例如MaxHeap和MinHeap。這些類(lèi)繼承自Heap類(lèi),并實(shí)現(xiàn)了具體的插入、刪除、獲取最大(或最?。┲档确椒?。下面我們以MaxHeap為例,來(lái)詳細(xì)介紹如何實(shí)現(xiàn)堆。
MaxHeap的實(shí)現(xiàn)思路如下:
定義一個(gè)數(shù)組來(lái)保存堆的元素,數(shù)組下標(biāo)從1開(kāi)始。
定義一個(gè)變量來(lái)記錄堆中元素的數(shù)量。
實(shí)現(xiàn)插入方法:新元素插入到數(shù)組最后,然后使用上濾操作將新元素沿著路徑向上移動(dòng),直到堆的性質(zhì)被滿(mǎn)足。
實(shí)現(xiàn)刪除方法:移除堆頂元素(數(shù)組下標(biāo)為1的元素),然后將數(shù)組最后一個(gè)元素替換到堆頂,使用下濾操作將新元素沿著路徑向下移動(dòng),直到堆的性質(zhì)被滿(mǎn)足。
實(shí)現(xiàn)獲取最大值方法:直接返回堆頂元素。
實(shí)現(xiàn)堆排序方法:依次取出堆頂元素,將其放到一個(gè)新的數(shù)組中,然后重新調(diào)整堆。
以下是MaxHeap的代碼實(shí)現(xiàn):
public class MaxHeap<T extends Comparable<T>> { private T[] heap; // 堆元素?cái)?shù)組 private int size; // 堆元素?cái)?shù)量 @SuppressWarnings("unchecked") public MaxHeap(int capacity) { heap = (T[]) new Comparable[capacity + 1]; // 數(shù)組下標(biāo)從1開(kāi)始 size = 0; } public void insert(T value) { if (size == heap.length - 1) { resize(); } heap[++size] = value; // 新元素插入到數(shù)組最后 swim(size); // 上濾操作 } public T deleteMax() { if (size == 0) { throw new NoSuchElementException(); } T max = heap[1]; // 堆頂元素 heap[1] = heap[size--]; // 將數(shù)組最后一個(gè)元素替換到堆頂 sink(1); // 下濾操作 heap[size + 1] = null; // 釋放舊的堆頂元素 return max; } public T getMax() { if (size == 0) { throw new NoSuchElementException(); } return heap[1]; } public void heapSort(T[] arr) { heapify(arr); // 初始化堆 for (int i = size; i > 0; i--) { arr[i - 1] = deleteMax(); // 依次取出堆頂元素 } } private void swim(int k) { while (k > 1 && heap[k].compareTo(heap[k / 2]) > 0) { // 父節(jié)點(diǎn)小于當(dāng)前節(jié)點(diǎn),上濾 swap(k, k / 2); k /= 2; // 移動(dòng)到父節(jié)點(diǎn) } } private void sink(int k) { while (2 * k <= size) { // 如果有左孩子 int j = 2 * k; if (j < size && heap[j].compareTo(heap[j + 1]) < 0) { // 選擇左右孩子中較大的那個(gè) j++; } if (heap[k].compareTo(heap[j]) >= 0) { // 如果父節(jié)點(diǎn)不小于孩子節(jié)點(diǎn),下濾結(jié)束 break; } swap(k, j); // 父節(jié)點(diǎn)和子節(jié)點(diǎn)交換 k = j; // 移動(dòng)到子節(jié)點(diǎn) } } private void heapify(T[] arr) { heap = (T[]) new Comparable[arr.length + 1]; size = arr.length; System.arraycopy(arr, 0, heap, 1, arr.length); // 復(fù)制數(shù)組元素到堆中 for (int i = size / 2; i >= 1; i--) { // 倒序下濾,從最后一個(gè)非葉子節(jié)點(diǎn)開(kāi)始 sink(i); // 下濾操作 } } private void resize() { int newSize = heap.length * 2; heap = Arrays.copyOf(heap, newSize); } private void swap(int i, int j) { T temp = heap[i]; heap[i] = heap[j]; heap[j] = temp; } }
上面的代碼實(shí)現(xiàn)了MaxHeap類(lèi),它支持插入、刪除、獲取最大值和堆排序等操作。堆排序的實(shí)現(xiàn)就是先將數(shù)組元素初始化成一個(gè)堆,然后依次取出堆頂元素,進(jìn)行排序。
MaxHeap類(lèi)中使用了泛型,可以存儲(chǔ)任意類(lèi)型的元素,只要實(shí)現(xiàn)了Comparable接口。使用時(shí),可以像下面這樣創(chuàng)建一個(gè)MaxHeap對(duì)象,然后調(diào)用其方法進(jìn)行操作:
MaxHeap<Integer> maxHeap = new MaxHeap<>(10); maxHeap.insert(3); maxHeap.insert(1); maxHeap.insert(4); maxHeap.insert(1); maxHeap.insert(5); System.out.println(maxHeap.deleteMax()); // 輸出:5 System.out.println(maxHeap.getMax()); // 輸出:4 Integer[] arr = {3, 1, 4, 1, 5}; maxHeap.heapSort(arr); System.out.println(Arrays.toString(arr)); // 輸出:[1, 1, 3, 4, 5]
總的來(lái)說(shuō),實(shí)現(xiàn)堆的關(guān)鍵在于實(shí)現(xiàn)上濾和下濾操作。上濾操作用于插入新元素時(shí),將其從葉子節(jié)點(diǎn)沿著路徑向上移動(dòng),下濾操作用于刪除堆頂元素時(shí),將最后一個(gè)元素從根節(jié)點(diǎn)沿著路徑向下移動(dòng),維護(hù)堆的性質(zhì)。堆排序的實(shí)現(xiàn)就是先將數(shù)組初始化成一個(gè)堆,然后依次取出堆頂元素,進(jìn)行排序。最后,需要注意的是,在Java中實(shí)現(xiàn)堆可以使用Heap類(lèi),但也可以自己實(shí)現(xiàn)一個(gè)堆類(lèi),可以根據(jù)具體需求進(jìn)行設(shè)計(jì)和優(yōu)化。
到此這篇關(guān)于Java實(shí)現(xiàn)堆算法的使用示例的文章就介紹到這了,更多相關(guān)Java 堆算法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
mybatis-flex實(shí)現(xiàn)多數(shù)據(jù)源操作
MyBaits-Flex內(nèi)置了功能完善的多數(shù)據(jù)源支持,本文主要介紹了mybatis-flex實(shí)現(xiàn)多數(shù)據(jù)源操作,具有一定的參考價(jià)值,感興趣的可以了解一下2024-06-06SpringBoot?上傳文件判空以及格式檢驗(yàn)流程
這篇文章主要介紹了SpringBoot?上傳文件判空以及格式檢驗(yàn)流程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03spring boot和spring cloud之間的版本關(guān)系
這篇文章主要介紹了spring boot和spring cloud之間的版本關(guān)系,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-08-08Maven項(xiàng)目部署到服務(wù)器設(shè)置訪問(wèn)路徑以及配置虛擬目錄的方法
今天小編就為大家分享一篇關(guān)于Maven項(xiàng)目部署到服務(wù)器設(shè)置訪問(wèn)路徑以及配置虛擬目錄的方法,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-02-02SpringBoot使用阿里OSS實(shí)現(xiàn)文件云存儲(chǔ)的方法
這篇文章主要介紹了SpringBoot使用阿里OSS實(shí)現(xiàn)文件云存儲(chǔ),本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-10-10Java微服務(wù)開(kāi)發(fā)之Swagger詳解
Swagger 是一個(gè)規(guī)范和完整的框架,用于生成、描述、調(diào)用和可視化 RESTful 風(fēng)格的 Web 服務(wù)??傮w目標(biāo)是使客戶(hù)端和文件系統(tǒng)作為服務(wù)器以同樣的速度來(lái)更新。文件的方法,參數(shù)和模型緊密集成到服務(wù)器端的代碼,允許API來(lái)始終保持同步2021-10-10淺談String類(lèi)型如何轉(zhuǎn)換為time類(lèi)型存進(jìn)數(shù)據(jù)庫(kù)
這篇文章主要介紹了String類(lèi)型如何轉(zhuǎn)換為time類(lèi)型存進(jìn)數(shù)據(jù)庫(kù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03springboot使用注解實(shí)現(xiàn)鑒權(quán)功能
這篇文章主要介紹了springboot使用注解實(shí)現(xiàn)鑒權(quán)功能,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧2024-12-12關(guān)于SpringSecurity認(rèn)證邏輯源碼分析
這篇文章主要介紹了關(guān)于SpringSecurity認(rèn)證邏輯源碼分析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-07-07