堆排序-java

這次主要講了堆排序和堆的基本構造,下一期會詳細講述堆的各種基本操作。

文章目錄

前言

一、堆排序

1.題目描述

2.堆

二、算法思路

1.堆的存儲

2. 結點下移down

3.結點上移up

4.堆的基本操作

5.堆的初始化

三、代碼如下

1.代碼如下:

2.讀入數據:

3.代碼運行結果

總結


前言

這次主要講了堆排序和堆的基本構造,下一期會詳細講述堆的各種基本操作。


提示:以下是本篇文章正文內容,下面案例可供參考

一、堆排序

1.題目描述

輸入一個長度為?n?的整數數列,從小到大輸出前?m小的數。

輸入格式

第一行包含整數?n?和?m。

第二行包含?n?個整數,表示整數數列。

輸出格式

共一行,包含?m?個整數,表示整數數列中前?m?小的數。

數據范圍

1≤m≤n≤100000,
1≤數列中元素≤1000000000

2.堆

圖2.1完全二叉樹示意圖?

完全二叉樹:一棵深度為k的有n個結點的二叉樹,對樹中的結點按從上至下、從左到右的順序進行編號,每一層最多有2^{n-1}個結點,除了最后一層,其余層的結點數都是滿的,且最后一層從左往右依次分布。

堆是一種基于完全二叉樹的數據結構。可以分為大根堆,小根堆。

大根堆:每個結點的值都大于或者等于其左右孩子的值。

小根堆:每個結點的值都小于或者等于其左右孩子的值。?

二、算法思路

1.堆的存儲

?圖1.1堆的存儲示例圖

我們用一個一維數組來存儲堆的值,下標來表示是哪個結點,下標為1就存儲根節點的值,下標為2存儲它的左孩子的值,下標為3存儲它的右孩子的值,我們就可以類比推理出任一結點的左孩子和右孩子的下標。例如下標為x的結點,它的左孩子在數組中存儲的下標就是2x,它的右孩子在數組中存儲的下標是2x+1。(注:下標從1開始

2. 結點下移down

?圖2.1示例一

?我們以一個小根堆為例,父結點的值要小于它的左右孩子結點。當我們將根節點修改為6后,此時小根堆的性質就被破壞了,那么我們就要對這個小根堆進行調整。

圖2.2示例二?

此時,我們需要與根節點的左右孩子進行比較,得出6的左孩子3是3個點中最小的,進行交換。此時小根堆的性質還沒維護好,此時我們還需要將6跟它的左右孩子進行比較,得出它的左孩子3是最小的,再將6和它的左孩子進行交換,此時檢查后發現,符合小根堆的性質。即我們將某一個值變大,那么在小根堆中它就要下移。

    //傳入結點下標public static void down(int x){int temp = x;//兩個if語句來找出3個結點中最小的結點的下標if(2 * x <= size && heap[2* x] < heap[temp]){temp = 2 * x;}if (2 * x + 1 <= size && heap[2*x + 1] < heap[temp]){temp = 2 * x + 1;}//說明此時結點不是最小值,進行交換,再遞歸處理看是否還需要交換if(temp != x){int t = heap[temp];heap[temp] = heap[x];heap[x] = t;down(temp);}}

3.結點上移up

?

圖3.1結點上移示例?

當我們把最右下角的結點值修改為2,此時小根堆的性質被破壞。我們把2和它的父結點進行比較得出2就是3個結點的最小值,2跟它的父結點進行交換;然后。此時的2再跟它的父結點進行比較得出2是3個結點中的最小值,將2跟它的父結點進行交換。此時檢查后,發現符合小根堆的性質。可以看出如果值變大的話,我們需要進行結點上移操作,即結點上移來維護小根堆的性質。

up操作我們只需要跟父親結點比就可以了。

    //傳入結點下標public static void up(int x){int t = x;int temp =  x / 2;if(temp >= 1 && heap[temp] > heap[t]){t = temp;}if(t != x){int arr = heap[t];heap[t] = heap[x];heap[x] = arr;up(t);}}

?

4.堆的基本操作

我們引入一個一維整型數組heap來存儲堆,一個整型變量size來表示堆中最后一個元素的下標或者堆中的元素個數。(數組下標0不用,我們從下標為1開始存儲)

向堆中插入一個數:我們則直接在數組最后一個元素后面加入一個值,最后一個元素的下標為size即head[++size] = x;此時我們要預防堆的性質是否被破壞,那么我們直接執行結點上移操作即可。up(size);

求堆中的最小值:小根堆中的根節點就是堆中的最小值即head[1]。

刪除最小值:即我們將根節點刪除了,在一維數組中第一個元素我們很難刪除,但是最后一個元素很容易刪除,我們只需要用最后一個元素將根節點覆蓋,然后將堆的大小減1即head[1] = head[size];dowx(1)來讓結點下移來維護堆的性質。

刪除任意一個元素:刪除下標為k的結點值,我們還是用堆中的最后一個元素將這個元素值進行覆蓋,然后將堆的大小減1即head[k] = head[size];size--;如果結點值變大的進行結點下移,結點值變小進行結點下移,那么我們直接down(k);up(k);因為它最后只會執行這兩個操作中的一個,這樣小根堆的性質也會被維護。

修改任意一個元素:修改下標為k的元素為x,那么我們需要head[k] = x;如果結點值變大的進行結點下移,結點值變小進行結點下移,那么我們直接down(k);up(k);因為它最后只會執行這兩個操作中的一個,這樣小根堆的性質也會被維護。

5.堆的初始化

圖5.1示例圖?

因為我們需要初始化建造一個小根堆,那么我們只需要從倒數第2層開始每一個結點進行結點下移操作就可以了。最后一層是葉子節點不需要進行結點下移操作。

        for(int i = 1; i <= n; i++){heap[i] = sc.nextInt();}size = n;//初始化建堆for(int i = n / 2;i > 0;i--){down(i);}

三、代碼如下

1.代碼如下:


import java.io.*;
import java.util.*;
public class 堆排序 {static PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));static int N = 100010;//存儲堆static int[] heap = new int[N];//堆中最后一個結點的下標,也是堆中元素的個數static int size = 0;public static void main(String[] args) throws Exception{Scanner sc = new Scanner(br);int n = sc.nextInt();int m = sc.nextInt();for(int i = 1; i <= n; i++){heap[i] = sc.nextInt();}size = n;//初始化建堆for(int i = n / 2;i > 0;i--){down(i);}while (m-- > 0){//打印最小值pw.print(heap[1] +" ");//刪除堆中的根節點,然后維護小根堆性質heap[1] = heap[size];size--;down(1);}pw.flush();}//傳入結點下標public static void down(int x){int temp = x;//兩個if語句來找出3個結點中最小的結點的下標if(2 * x <= size && heap[2* x] < heap[temp]){temp = 2 * x;}if (2 * x + 1 <= size && heap[2*x + 1] < heap[temp]){temp = 2 * x + 1;}//說明此時結點不是最小值,進行交換,再遞歸處理看是否還需要交換if(temp != x){int t = heap[temp];heap[temp] = heap[x];heap[x] = t;down(temp);}}//傳入結點下標public static void up(int x){int t = x;int temp =  x / 2;if(temp >= 1 && heap[temp] > heap[t]){t = temp;}if(t != x){int arr = heap[t];heap[t] = heap[x];heap[x] = arr;up(t);}}
}

2.讀入數據:

5 3
4 5 1 3 2

3.代碼運行結果

1 2 3 

總結

上述通過一些堆的基本操作來完成堆排序,后續會專門再寫一次博客來詳細介紹模擬堆的各種操作。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/21130.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/21130.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/21130.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Harmony os Next——關系型數據庫relationalStore.RdbStore的使用

Harmony os Next——關系型數據庫relationalStore.RdbStore的使用 描述數據庫的使用建表定義表信息創建數據庫表 創建數據庫操作對象增更新查詢刪數據庫的初始化 描述 本文通過存儲一個簡單的用戶信息到數據庫中為例&#xff0c;進行闡述relationalStore.RdbStore數據庫的CRUD…

小公司的軟件開發IT工具箱

目錄 工具鏈困境 難題的解決 達到的效果 資源要求低 工具箱一覽 1、代碼管理工具 2、自動化發版&#xff08;測試&#xff09;工具 3、依賴庫&#xff08;制品包&#xff09;管理 4、鏡像管理 5、授權管理&#xff08;可選&#xff09; 待討論&#xff1a;為什么不是…

LeetCode17電話號碼的字母組合

題目描述 給定一個僅包含數字 2-9 的字符串&#xff0c;返回所有它能表示的字母組合。答案可以按 任意順序 返回。 給出數字到字母的映射如下&#xff08;與電話按鍵相同&#xff09;。注意 1 不對應任何字母。 解析 廣度優先遍歷或者深度優先遍歷兩種方式&#xff0c;廣度優先…

springboot動態切換數據源

1、創建一個springboot項目&#xff0c;導入依賴&#xff08;3.3.0&#xff09; <dependency><groupId>com.baomidou</groupId><artifactId>dynamic-datasource-spring-boot-starter</artifactId><version>3.6.1</version></depe…

滲透測試靶機----FirstLeads_1.3

滲透測試靶機----FirstLeads_1.3 啟動靶機&#xff0c;掃描ip&#xff0c;平平無奇 可以看出&#xff0c;這里是存在139這個主機的&#xff0c;這就是掃描出來的靶機ip繼續探測端口及其他信息 發現這里只開啟了80 端口 嘗試一些基本目錄&#xff0c;發現存在robot.txt文件目錄…

集成算法:Bagging模型、AdaBoost模型和Stacking模型

概述 目的&#xff1a;讓機器學習效果更好&#xff0c;單個不行&#xff0c;集成多個 集成算法 Bagging&#xff1a;訓練多個分類器取平均 f ( x ) 1 / M ∑ m 1 M f m ( x ) f(x)1/M\sum^M_{m1}{f_m(x)} f(x)1/M∑m1M?fm?(x) Boosting&#xff1a;從弱學習器開始加強&am…

插入排序以及希爾排序; 先學會插入,希爾會更簡單喔

1.前言 首先肯定是要學會插入排序再學習希爾排序會更簡單&#xff0c;因為代碼部分有很多相似之處&#xff1b;如果你覺得你很強&#xff0c;可以直接看希爾排序的講解。哈哈哈&#xff01;&#xff0c;每天進步一點點&#xff0c;和昨天的自己比 2.插入排序 讓我們先來看看…

鴻蒙Ability Kit(程序框架服務)【UIAbility組件與UI的數據同步】

UIAbility組件與UI的數據同步 基于當前的應用模型&#xff0c;可以通過以下幾種方式來實現UIAbility組件與UI之間的數據同步。 [使用EventHub進行數據通信]&#xff1a;在基類Context中提供了EventHub對象&#xff0c;可以通過發布訂閱方式來實現事件的傳遞。在事件傳遞前&am…

Rustdesk 自建服務器教程

一、環境 阿里云輕量服務器、debian11 系統 二、服務端搭建 2.1、開放防火墻指定端口 TCP(21115, 21116, 21117, 21118, 21119)UDP(21116) 2.2、安裝 rustdesk 服務器文件 在 github 下載頁https://github.com/rustdesk/rustdesk-server/releases/&#xff0c;下載 rustde…

【自撰寫,國際象棋入門】第1課、棋盤和棋子

第1課 棋盤和棋子 一、國際象棋的棋盤 國際象棋的棋盤為一8乘8的黑、白格相間的棋盤&#xff0c;8條豎線的編號分別為A-H&#xff0c;8條橫線的編號分別為1-8&#xff0c;在記譜時用豎線編號橫線編號的方式表示棋盤上的格子&#xff0c;例如a1格、h8格等.棋盤上有幾條重要的大…

c++程序員為什么要做自己的底層庫

五一期間&#xff0c;在家里翻到之前上學時候用的電腦和工作日志&#xff0c;粗略瀏覽一番&#xff0c;感慨10年歲月蹉跎&#xff0c;仍然沒有找到自己技術方向的“道”。遂有感而發&#xff0c;寫下此文。 算起來&#xff0c;接觸軟件開發也有10年時間了&#xff0c;最開始是…

Java——異常

1.什么是異常 將程序執行過程中發生的不正常行為稱為異常。 常見的異常有&#xff1a;算數異常&#xff0c;空指針異常&#xff0c;數組越界異常 每一種異常都有對應的類對齊描述 為了對每一種異常進行管理&#xff0c;Java內部實現了一個對異常的體系結構 1. Throwable&#x…

CS2游戲30萬掛箱賬號被封,飾品市場要變天

Steam游戲平臺上CS2的玩家在線人數常年位于第一位&#xff0c;即便偶爾會被爆款游戲擠下來&#xff0c;但一切都是暫時的。飾品交易作為CS2的重要組成部分&#xff0c;早已成為了維系游戲熱度的不二法門。可相對應的&#xff0c;各種掛箱子的工作室及個人也孕育而生。 但近來V社…

mysql多啟動

binary安裝&#xff1a; 1、redhat rpm 2、mysql rpm 3、mysql glibc source安裝&#xff1a; 1、5.1mysql(./configure && make && make install) 2、5.5mysql(cmake && make && make install) 單啟動&#xff1a; 1、安裝 tar xf xxx.tar…

【Docker學習】docker pull詳細說明

docker pull是我們經常用到的一個命令。我們使用一些官方鏡像&#xff0c;如MySql、Nginx等都需要用docker pull下載。不過不用的話&#xff0c;也可以。比如使用docker run&#xff0c;要是找不到鏡像&#xff0c;會自動下載。 命令&#xff1a; docker image pull 描述&am…

Uniapp寫一個簡單的商品瀑布流界面+商品詳情

最終效果&#xff1a; 整體內容比較簡單&#xff0c;參考了一篇瀑布流文章和一篇商品詳情文章隨便修改整了下&#xff0c;主要是給想做這方便面的新人一個簡單邏輯的展示&#xff08;其實我也是第一次寫這個emmm&#xff09; 一.組件下載&#xff1a; uni-icon uni-goods-nav…

什么是ACP?

前言 ACP指的是應用程序控制平面&#xff0c;是微服務架構中的一個關鍵組成部分。它負責管理微服務架構中的各個微服務&#xff0c;包括服務發現和注冊、負載均衡、服務路由、熔斷和降級、配置管理等方面的功能。 A&#xff1a;可用性 所有請求都有響應。C&#xff1a;強一致…

[DDR5 Jedec 3-4] 模式寄存器 Mode Register MRR/MRW

依公知及經驗整理,原創保護,禁止轉載。 專欄 《深入理解DDR》 1. 概念 模式寄存器用于定義各種操作模式。在初始化過程中,可以通過重新執行MRS命令來更改模式寄存器的內容。即使用戶只想修改模式寄存器變量的一個子集,在發出MRS命令時也必須編程所有變量。 只有當所有ban…

C語言案例-輸入任意三個數,按從大到小的順序輸出.

目錄 問題待續、更新中 問題 輸入任意三個數,按從大到小的順序輸出. 最大值 3數&#xff0c;重新排序輸出 輸出數據if來&#xff0c;ab ac bc比&#xff0c;比中里面交換值&#xff0c;輸出abc時為降序 代碼如下: #include <stdio.h> void main() {int a,b,c,t;printf(&…

現實殘酷!存款百萬只是少數人的游戲,普通家庭能存多少?

近期&#xff0c;網絡上掀起了一股關于普通家庭終身存款上限的熱烈討論。一位網友通過簡單的算術方式提出了一個假設&#xff1a;如果一對夫妻每年收入15萬&#xff0c;并成功將6萬存入銀行&#xff0c;那么從25歲步入社會至60歲退休&#xff0c;他們理論上能積累到210萬的存款…