快速排序和堆排序

2020-12-16 龜哥淺談網際網路一角

龜哥今天和大家分享下快速排序,堆排序算法。

首先快速排序的思想,給定一個無序的數組,首先用兩個指針left和right分別指向數組的頭部和尾部,將數組的第一個元素array[0]作為和left,right指針比較的元素。如果將無序的數組排列成從小到大的有序數組的話,首先right指針array[array.length-1]數組的最後一個元素,array[array.length-1]和array[0]進行比較,如果array[array.length-1]>array[0],則右指針往左移,直到找到一個元素比array[0]小的元素,跳出循環。同理做指針與array[0]比較,直到找到一個比array[0]大的跳出循環,然後進行交換,小於array[0]在左邊,大於array[0]的在右邊,最後是遞歸調用函數。那龜哥踩過的坑是沒有判斷

if(low>high){ return; }造成執行錯誤的情況。核心代碼:

while(i<j) {

while(temp<=array[j]&&i<j) {

j--;}

while(temp>=array[i]&&i<j) {

i++;}

if(i<j) {

int t=array[j];

array[j]=array[i];

array[i]=t;} }

array[low]=array[i];

array[i]=temp;

func(array,low,j-1);

func(array,j+1,high);

第二個龜哥分享的是堆排序,它的思想首先建堆,然後堆排序。初始建堆:

for(int i=(array.length-2)/2;i>=0;i--) {

adjustDownToUp(array,i,array.length); }初始建堆的時候我們從最後一個非葉子節點開始,調用調整堆adjustDownToUp的函數。

public static void adjustDownToUp(int[] array, int k, int length) {

int temp=array[k]; //首先拿到依次拿到非葉子節點的數據

for(int i=2*k+1;i<length-1;i=2*i+1) {

if(i<length && array[i]<array[i+1]) {//如果父節點的左節點的值大於右節點的值

i++; }

if(temp>array[i]) {//如果父節點的值大於任何一個節點的值,符合大頂堆,不再進行比較

break;

}else {

array[k]=array[i];//如果父節點的值不大於較大節點的值,把較大節點的值賦值給k

k=i;//把i的索引賦值給k索引} }

array[k]=temp;//然後將父節點k賦值給i的索引。}

初始堆構建完成後,最後一步是堆排序,初始堆中根節點是最大值,把這個最大值放到有序數列中,和最後一個葉節點進行交換,就是說交換後最後一個節點i之前的數據都是無序的,需要重新進行構建,然後根節點又找到一個,和i-1進行交換,知道n-1次交換完成,直至使變成有序數組。

for(int i=array.length-1;i>1;i--) {

//找到根節點的最大值與array[0]進行交換

int temp=array[0];

array[0]=array[i];

array[i]=temp;

adjustDownToUp(array,0,i);}

好了 龜哥的分享就到這了,又什麼問題可以留言呀

相關焦點

  • 詳解堆排序
    堆中有兩個父結點,元素3和元素8。元素3在數組中以R[0]表示,它的左孩子結點是R[1],右孩子結點是R[2]。元素8在數組中以R[1]表示,它的左孩子結點是R[3],右孩子結點是R[4],它的父結點是R[0]。
  • 優先級隊列與堆排序
    本文首先介紹優先級隊列的定義,有序和無序數組以及堆數據結構實現優先級隊列,最後介紹了基於優先級隊列的堆排序(Heap Sort)一 定義優先級隊列和通常的棧和隊列一樣,只不過裡面的每一個元素都有一個」優先級」,在處理的時候,首先處理優先級最高的。如果兩個元素具有相同的優先級,則按照他們插入到隊列中的先後順序處理。
  • 堆排序就這麼簡單
    一、堆排序介紹來源百度百科:堆排序(Heapsort)是指利用堆積樹(堆)這種數據結構所設計的一種排序算法,它是選擇排序的一種。可以利用數組的特點快速定位指定索引的元素。堆分為大根堆和小根堆,是完全二叉樹。前面我已經有二叉樹入門的文章了,當時講解的是二叉查找樹,那上面所說的完全二叉樹是怎麼樣的一種二叉樹呢??
  • 第二篇,選擇排序算法:簡單選擇排序、堆排序
    簡介選擇排序的基本思想是:每一趟(如第i趟)在後面 n-i+1 ( i = 1 , 2, ...., n-1) 個待排序元素中選取關鍵字最小的元素,作為有序子序列的第i個元素,直到第 n-1 趟做完,待排序元素只剩下一個,就不用再選了。    基於選擇的排序算法主要介紹簡單選擇排序和堆排序。
  • 八十四、堆排序解決TopK問題
    「@Author:Runsen」上次介紹了堆排序,這次介紹堆排序常見的應用場景TopK問題。利用堆求TopK問題TopK問題是一個堆排序典型的應用場景。至於為什麼TopK問題最佳的答案是堆排序?其實在空間和時間的複雜度來考量,雖說快排是最好的排序算法,但是對於100億個元素從大到小排序,然後輸出前 K 個元素值。可是,無論我們掌握的是快速排序算法還是堆排序算法,在排序的時候,都需要將全部的元素讀入到內存中。
  • 堆排序與拓撲排序(Java模板)
    1.堆排序思想(1) 以升序排序為例,我們需要構建一個小根堆。第一種方法:用數組模擬小根堆。忘記了的朋友可以看看之前的文章《堆模板(Java)》認真複習一下~第二種方法:使用 java.util.PriorityQueue ,相當於一個堆結構。
  • 圖解:什麼是堆排序?
    二叉堆(Binary Heap)是一顆特殊的完全二叉樹,一般分為大頂堆和小頂堆,我就不囉嗦啦!具體內容你可以看一下 圖解:什麼是二叉堆?堆排序 要學習今天的堆排序(Heap Sort),我們以一個數組  arr = [5、1、4、2、8、4] 開始(這個數組我們之前講排序算法常用的):我們首先以這個數組建立一個大頂堆,插入結點 5 作為根結點
  • 一文讀懂堆排序
    (點擊上方公眾號,可快速關注)轉自:劉毅https://61mon.com/index.php/archives/202/
  • ...選擇,插入,希爾,歸併,快排,堆排序,計數排序,桶排序,基數排序)
    ;外排序:由於數據很大,因此把數據放在磁碟中,排序通過磁碟和內存的數據傳輸才能進行。,我們可以每一趟排序中進行正向和反向兩遍冒泡,一次可以得到兩個最終值(最大和最小),從而是排序趟數減少了一半。,i-1]和無序區R[i,...,n]。從該趟排序從當前無序區中選出關鍵字最小的記錄R[k],將R[k]與無序區的第一個記錄R[1]交換,使無序區R[1,...,i]減少1個,和有序區R[i+1,...,n]增加1個。
  • 重溫7種排序算法 第一篇,交換排序算法:冒泡排序、快速排序
    排序算法可分為以下幾類:    交換排序算法:冒泡排序、快速排序;    選擇排序算法:簡單選擇排序、堆排序;    插入排序算法:直接插入排序、希爾排序;    歸併排序算法。    主要做了以上7種排序算法的筆記,字數可能較多,所以分為幾篇。
  • 堆排序算法
    大頂堆:a[i] >=a[2i+1] && ar[i] >= a[2i+2] 小頂堆:a[i] <= a[2i+1] && a[i] <= a[2i+2] 堆排序的基本思想:
  • 動畫 | 什麼是堆排序?
    而堆排序因為二叉堆的性質,堆頂就是最大的元素,查找次數只有一次,但是將無序轉成有序中間還需要一個預處理過程:構造堆有序。 堆有序並不代表數組有序,堆有序是滿足 二叉堆 性質的: 1.父節點的鍵值總是優先於任何一個子節點的鍵值; 2.左右子樹都是一個二叉堆。
  • 堆排序原理及實現
    小白們也很熟悉的:冒泡,歸併,簡單選擇,歸併,堆排序。那它們區別是什麼呢?需要好好梳理一下了。今天咱們就先瞅瞅感覺比較抽象的堆算法吧。什麼是堆?堆是具有下列性質的完全二叉樹:每個結點的值都大於或等於其左右孩子結點的值,稱為大頂堆;或者每個結點的值都小於或等於其左右子結點的值,稱為小頂堆。
  • 到底什麼是堆排序 PHP
    每個節點的值都大於等於子樹中每個節點值的堆叫最大堆,反之為最小堆。堆排序的時間複雜度為O(nlogn)。堆是一種特殊的二叉樹,它滿足以下兩點:1. 堆是一個完全二叉樹2. 堆中每個節點都必須大於等於(或小於等於) 其子樹的每個節點
  • 堆排序算法C語言詳解
    通過將無序錶轉化為堆,可以直接找到表中最大值或者最小值,然後將其提取出來,令剩餘的記錄再重建一個堆,取出次大值或者次小值,如此反覆執行就可以得到一個有序序列,此過程為堆排序。堆排序過程的代碼實現需要解決兩個問題:如何將得到的無序序列轉化為一個堆?在輸出堆頂元素之後(完全二叉樹的樹根結點),如何調整剩餘元素構建一個新的堆?
  • 排序算法問題:穩定排序與不穩定排序
    4、快速排序 快速排序有兩個方向,左邊的i下標一直往右走,當a[i] <= a[center_index],其中center_index是中樞元素的數組下標,一般取為數組第0個元素。而右邊的j下標一直往左走,當a[j] > a[center_index]。
  • 深入理解快速排序和 STL 的 sort 算法
    4.1 快速排序vs歸併排序快速排序和歸併排序採用的基本思想都是分治思想Divide&Conquer,從D&C思想來看最主要的部分就是分割和合併,兩種算法在使用D&C時側重點有一些差異:歸併排序在分割時處理很簡單,在合併時處理比較多,重點在合併。
  • 排序算法:快速排序
    在日常開發中經常會遇到一類問題,就是對一個集合的數據進行排序掌握一些排序算法,對於日常開發是非常有幫助今天介紹一下快速排序法01算法邏輯02時間複雜度由上圖邏輯可以得出,參照遞歸表達式漸進複雜度分析快速排序的時間複雜度遞歸表達式為,其中a=2,b=2,d=1由算法導論的主定理可以推導出,快速排序的時間複雜度為03空間複雜度由上圖邏輯可以得出
  • 分而治之和快速排序
    二、快速排序2.1 快速排序原理第一個重要的D&C算法-快速排序,快速排序是一種排序算法。速度比選擇排序快得多。使用快速排序對數組進行排序,對排序算法來說,最簡單的數組是什麼樣子的呢?就是根本不需要排序的數組。例如:空數組和只包含一個元素的數組。所以基線條件為數組為空數組或者數組只包含一個元素,在這種情況下,只需要原樣返回數組,根本不需要排序。
  • 徹底搞懂穩定排序與不穩定排序
    如果i和j都走不動了,i <= j,交換a[i]和a[j],重複上面的過程,直到i > j。 交換a[j]和a[center_index],完成一趟快速排序。在中樞元素和a[j]交換的時候,很有可能把前面的元素的穩定性打亂,比如序列為5 3 3 4 3 8 9 10 11,現在中樞元素5和3(第5個元素,下標從1開始計)交換就會把元素3的穩定性打亂,所以快速排序是一個不穩定的排序算法,不穩定發生在中樞元素和a[j] 交換的時刻。