算法入門篇三 詳解桶排序和整理排序知識 堆的相關操作 補充 不完整

歸并排序不使用遞歸

  • 使用一個變量,使其按照1、2、4、8遞增,控制左右兩邊1個元素、2個元素、4個元素等元素的合并

完全二叉樹

  • 完全二叉樹 要不全是滿的,要不葉子節點出現在最后一層,只要出現了葉子節點,后面的都是葉子節點
  • 完全二叉樹可以用數組下標從0-7來表示,依據以下公式計算左節點、右節點和父節點
  • 對于任意節點 i?
  • 左節點? 2*i+1
  • 右節點? 2*i+2
  • 父節點? (i-1)/2

堆(完全二叉樹)

大根堆

  • 在完全二叉樹上,每一個子樹的最大值都是頭節點

小根堆

  • 在完全二叉樹上,每一個子樹的最小值都是頭節點

堆的插入和刪除操作是O(logn),構建堆的操作是O(n)

堆的存儲方式不是鏈式存儲,而是順序存儲。左孩子下標是 2*parent +1;右孩子下標是2 * parent+2

優先隊列:比如最大優先隊列,讓最大的元素出隊,即使最大元素不在隊頭,他仍然是第一個出隊,因為它優先級最高。優先隊列的底層是使用大根堆來實現的。每一次入隊操作就是堆的插入操作,每一次出隊操作就是刪除堆頂點

因為二叉堆的上浮和下沉的時間復雜度都是O(logn),因此優先隊列的入隊和出隊的時間復雜度也是O(logn)

例子

  • 加入元素:數組下標從0到7,按照輸入的順序加入到數組中,沒加入一個數組根據公式(i-1)/ 2來判定,他的父節點的位置,然后與父節點做比較,如果大于父節點則和父節點的位置交換。每加入一個元素,那么heapsize+1。heapsize用于指定堆的大小。
  • 返回最大值:將大根堆的最頂端和最末尾的元素相互交換,然后將heapsize-1,返回最頂端的數值。末尾元素移到最頂端之后,需要找到它的左右兩個孩子節點,做比較,如果有比它還大的孩子節點就進行交換。依此類推。
  • 數組擴容:如果原始只分配一個字節,動態加入元素,進行數組擴容。那么需要log(N)次數的擴容,最后需要拷貝N個數到擴容完成后的數組中;因此代價是 N*log(N),如果取平均,最后代價是log(N)

完整代碼

  • heapsort方法適用于 將元素插入數組,一個一個往里面放
  • heapify 適用于如果將元素彈出的時候,將最小的元素放在頂端,看其是否下降
  • 還不是很了解 這個代碼的含義
package class02;import java.util.Arrays;
import java.util.PriorityQueue;public class Code03_HeapSort {public static void heapSort(int[] arr) {if (arr == null || arr.length < 2) {return;}for (int i = 0; i < arr.length; i++) { // O(N)heapInsert(arr, i); // O(logN)}// for(int i = arr.length -1; i >=0; i--) {// heapify(arr, i, arr.length);// }int heapSize = arr.length;swap(arr, 0, --heapSize);while (heapSize > 0) { // O(N)heapify(arr, 0, heapSize); // O(logN)swap(arr, 0, --heapSize); // O(1)}}// arr[0 ... index-1]已經是堆了某個數現在處在index位置,往上繼續移動public static void heapInsert(int[] arr, int index) {while (arr[index] > arr[(index - 1) / 2]) {swap(arr, index, (index - 1) / 2);index = (index - 1) / 2;}}// 某個數在index位置,能否往下移動public static void heapify(int[] arr, int index, int heapSize) {int left = index * 2 + 1; // 左孩子的下標while (left < heapSize) { // 下方還有孩子的時候// 兩個孩子中,誰的值大,把下標給largestint largest = left + 1 < heapSize && arr[left + 1] > arr[left] ? left + 1 : left;// 父和較大的孩子之間,誰的值大,把下標給largestlargest = arr[largest] > arr[index] ? largest : index;if (largest == index) {break;}swap(arr, largest, index);index = largest;left = index * 2 + 1;}}public static void swap(int[] arr, int i, int j) {int tmp = arr[i];arr[i] = arr[j];arr[j] = tmp;}// for testpublic static void comparator(int[] arr) {Arrays.sort(arr);}// for testpublic static int[] generateRandomArray(int maxSize, int maxValue) {int[] arr = new int[(int) ((maxSize + 1) * Math.random())];for (int i = 0; i < arr.length; i++) {arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());}return arr;}// for testpublic static int[] copyArray(int[] arr) {if (arr == null) {return null;}int[] res = new int[arr.length];for (int i = 0; i < arr.length; i++) {res[i] = arr[i];}return res;}// for testpublic static boolean isEqual(int[] arr1, int[] arr2) {if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) {return false;}if (arr1 == null && arr2 == null) {return true;}if (arr1.length != arr2.length) {return false;}for (int i = 0; i < arr1.length; i++) {if (arr1[i] != arr2[i]) {return false;}}return true;}// for testpublic static void printArray(int[] arr) {if (arr == null) {return;}for (int i = 0; i < arr.length; i++) {System.out.print(arr[i] + " ");}System.out.println();}// for testpublic static void main(String[] args) {int index = -1;System.out.println(index / 2);int testTime = 500000;int maxSize = 100;int maxValue = 100;boolean succeed = true;for (int i = 0; i < testTime; i++) {int[] arr1 = generateRandomArray(maxSize, maxValue);int[] arr2 = copyArray(arr1);heapSort(arr1);comparator(arr2);if (!isEqual(arr1, arr2)) {succeed = false;break;}}System.out.println(succeed ? "Nice!" : "Fucking fucked!");int[] arr = generateRandomArray(maxSize, maxValue);printArray(arr);heapSort(arr);printArray(arr);}}

比較器的使用

  • 實質:重載比較運算符
  • 比較器可以應用在特殊標準的排序上
  • 比較器可以應用在特殊標準的排序結構上
  • 自己定義比較規則? 類似 C++運算符號重載,比如定義一個學生結構體,包含學生的名字、年齡和id;通過結構的年齡的比較,進行排序

堆排序的擴展題目

  • 已知一個幾乎有序的數組,幾乎有序是指,如果將數組排好順序的話,每個元素的移動距離不超過k,并且k相對于數組來說比較小。請選擇一個合適的排序算法針對這個數據進行排序
  • 思路:使用一個大小為 k+1 的內存空間,主要目的是要小根堆,先將k+1個元素放入申請的內存空間,每次放入都需要進行一次調整;此時0位置的元素是最小的元素;然后將0位置元素彈出,再將新的元素插入申請的空間,進行調整。(每彈出一個首元素,再插入一個新的元素,整體調整)?(每個數進入一次彈出一次,N*logk)
  • ?

?

?

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

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

相關文章

C++著名程序庫

1、C各大有名庫的介紹——C標準庫標準庫中提供了C程序的基本設施。雖然C標準庫隨著C標準折騰了許多年&#xff0c;直到標準的出臺才正式定型&#xff0c;但是在標準庫的實現上卻很令人欣慰得看到多種實現&#xff0c;并且已被實踐證明為有工業級別強度的佳作。 1.1、Dinkumware…

2023年12月24日學習總結

今日to do list&#xff1a; 做kaggle上面的流量預測項目?? 學習時不刷手機&#x1f921; okkkkkkkkkkkkkk 開始&#x1f44d;&#x1f34e; 0、我在干什么&#xff1f; 我在預測一個名字叫做elborn基站的下行鏈路流量&#xff0c;用過去29天的數據預測未來10天的數據 1、…

Mac/Linux系統連接遠端服務器以及相同IP地址的服務器賬號密碼重置,ssh失敗問題

連接遠端服務器 ssh 賬號IP地址 輸入完成之后會提示輸入密碼&#xff0c;密碼輸入正確后&#xff0c;就可以連接成功了 重置ssh密鑰 如果連接的服務器除了IP地址沒有改變&#xff0c;其余的賬號、密碼、系統等都變了的話&#xff0c;因為曾經連接過的歷史數據會保存到本地&a…

內存泄漏快速定位方法

主要方法&#xff1a;利用系統帶的函數&#xff1a;EnableMemLeakCheck() 和函數重載&#xff0c;能快速準備的定位到內存泄漏的地方&#xff0c;方法簡單且實用&#xff0c;值得借用。 #include <crtdbg.h> #ifdef_DEBUG //重載一下new函數&#xff0c;這樣能得到使…

Linux操作系統監視NVIDIA的GPU使用情況

對于GPU相關參數介紹 使用命令周期性查看GPU運行情況最常用的參數是 -n&#xff0c; 后面指定是每多少秒來執行一次命令。監視顯存&#xff1a;設置為每 1s 顯示一次顯存的情況&#xff1a;使用命令ctrlz退出 watch -n 1 nvidia-smi 參數介紹 Fan&#xff1a;顯示風扇轉速&am…

一個軟件工程師的職業規劃

[1]好好規劃自己的路&#xff0c;不要跟著感覺走&#xff01;根據個人的理想決策安排&#xff0c;絕大部分人并不指望成為什么院士或教授&#xff0c;而是希望活得滋潤一些&#xff0c;爽一些。那么&#xff0c;就需要慎重安排自己的軌跡。從哪個行業入手&#xff0c;逐漸對該行…

算法入門篇四 桶排序

桶排序 計數排序&#xff08;基于統計&#xff09; 要求數據是有限的&#xff0c;和數據狀況有關&#xff0c;比如對于200個人統計他們的年齡分布&#xff0c;這個時候需要申請200個桶&#xff0c;因此對于輸入數據的規模有限制&#xff0c;如果輸入規模是不定的&#xff0c;…

RTP概述

1.1. RTP是什么 RTP全名是Real-time Transport Protocol&#xff08;實時傳輸協議&#xff09;。它是IETF提出的一個標準&#xff0c;對應的RFC文檔為RFC3550&#xff08;RFC1889為其過期版本&#xff09;。RFC3550不僅定義了RTP&#xff0c;而且定義了配套的相關協議RTCP&…

Java需要注意的一些小細節

更加精確的鎖定時間 判定納秒維度的時間 //使用System.nanoTime(); //例子 long start System.nanoTime(); long end System.nanoTime(); System.out.println(start); System.out.println(end);

live555的安裝 RTSP點播消息流程實例(客戶端:VLC, RTSP服務器:LIVE555 Media Server)

live555是一個開源的軟件&#xff0c;主要用來生成rtsp,rtp和sip服務器和客戶端的軟件。前幾天需要看一下vlc中的rtsp的功能&#xff0c;在vlc中rtp和rtsp的功能都是使用live555中的函數來生成的。該開源軟件的編譯&#xff0c;可以使用vc,mingw和cygwin等軟件。我安裝的時候使…

算法入門篇五 鏈表

牛客網 算法入門篇 判斷一個鏈表是否為回文結構 給定一個單鏈表的頭節點head&#xff0c;請判斷這個鏈表是否為回文結構1->2->1&#xff0c;返回為True;1->2->3為False 思路&#xff1a; 1&#xff0c;遍歷鏈表&#xff0c;將所有元素壓入棧中&#xff0c;然后再…

實時流媒體編程基于Linux環境開發

一、流媒體簡介 隨著Internet的日益普及&#xff0c;在網絡上傳輸的數據已經不再局限于文字和圖形&#xff0c;而是逐漸向聲音和視頻等多媒體格式過渡。目前在網絡上傳輸音頻/視頻&#xff08;Audio/Video&#xff0c;簡稱A/V&#xff09;等多媒體文件時&#xff0c;基本上只有…

算法入門篇六 二叉樹

牛客網 算法入門篇 左程云老師 個人復習&#xff0c;如果侵全&#xff0c;設為私密 二叉樹遍歷&#xff08;遞歸&#xff09; 先序遍歷&#xff08;中&#xff0c;左&#xff0c;右&#xff09; 中序遍歷&#xff08;左&#xff0c;中&#xff0c;右&#xff09; 后序遍歷&a…

VLC詳細的使用說明以及配置說明綜合示范實例精通VLC開發

vlc的全名是Video LanClient&#xff0c;是一個開源的、跨平臺的視頻播放器。VLC支持大量的音視頻傳輸、封裝和編碼格式&#xff0c;完整的功能特性列表可以在這里獲得http://www.videolan.org/vlc/features.html&#xff0c;下面給出一個簡要的不完整的列表&#xff1a;操作系…

算法入門篇七 前綴樹

牛客網 左程云老師的算法入門課 找二叉樹的節點的后繼節點 原則 如果節點有右子樹&#xff0c;那么后繼節點就是右子樹的最左邊的第一個節點如果節點沒有右子樹&#xff0c;如果節點是父節點的右孩子&#xff0c;就繼續往上找&#xff0c;直到找到一個父節點是沿途節點的父節…

VLC視頻播放器原理詳細分析含TS流格式分析

vlc是一個功能強大的玩意&#xff0c;能做很多有意思的事情。最簡單的&#xff0c;從界面打開一個文件播放&#xff0c;也可以在命令行下使用&#xff0c;如C:\Program Files\VideoLAN\VLC>vlc.exe test.ts獲取內置的幫助&#xff0c;會寫到vlc-help.txtC:\Program Files\Vi…

算法入門篇八 貪心算法

牛客網 左程云老師的算法入門課 貪心算法 貪心算法的解題步驟 例子 題目要求 解題策略 按照結束時間早的會議先安排&#xff0c;比如先安排【2&#xff0c;4】&#xff0c;當4結束了&#xff0c;所有開始時間小于4的全部淘汰&#xff0c;【1&#xff0c;7】、【3&#xff…

算法入門篇九 暴力遞歸

牛客網 左程云老師的算法入門課 暴力遞歸 原則 漢諾塔問題 問題 打印n層漢諾塔從左邊移動到最右邊的過程 思想 一共六個過程&#xff0c;左到右、左到中&#xff0c;中到左&#xff0c;中到右&#xff0c;右到左&#xff0c;右到中&#xff0c;互相嵌套使用 左到右 將1…

rtsp和sdp

RTSP 是由Realnetwork 和Netscape共同提出的如何有效地在IP網絡上傳輸流媒體數據的應用層協議 。 實時流協議&#xff08;RTSP&#xff09;建立并控制一個或幾個時間同步的連續流媒體&#xff0c;如音頻和視頻。盡管連續媒體流與控制流交叉是可能的&#xff0c;RTSP本身并不發…

使用javascript實現對于chineseocr的API調用

ChineseOCR在線API 網頁地址 界面 提供多種接口調用方式&#xff0c;比如在線調用、Javascript api調用、curl api調用和python api調用四種方式&#xff0c;本次使用javascript api調用的方式進行OCR識別在線Javascript工具 在線工具網頁鏈接在線Base64 轉化工具 在線工具…