基礎不牢地動山搖記住 Java 面試中常用的八種排序算法與代碼實現

2020-12-16 酷扯兒

本文轉載自【微信公眾號:java進階架構師,ID:java_jiagoushi】經微信公眾號授權轉載,如需轉載與原文作者聯繫

1.直接插入排序

經常碰到這樣一類排序問題:把新的數據插入到已經排好的數據列中。

將第一個數和第二個數排序,然後構成一個有序序列將第三個數插入進去,構成一個新的有序序列。對第四個數、第五個數……直到最後一個數,重複第二步。

如何寫成代碼:

首先設定插入次數,即循環次數,for(int i=1;i<length;i++),1個數的那次不用插入。< span>設定插入數和得到已經排好序列的最後一個數的位數。insertNum和j=i-1。從最後一個數開始向前循環,如果插入數小於當前數,就將當前數向後移動一位。將當前數放置到空著的位置,即j+1。代碼實現如下:

public void insertSort(int[] a){int length=a.length;//數組長度,將這個提取出來是為了提高速度。 int insertNum;//要插入的數 for(int i=1;i<length;i++){//插入的次數 insertNum=a[i];//要插入的數 int j=i-1;//已經排序好的序列元素個數 while(j>=0&&a[j]>insertNum){//序列從後到前循環,將大於insertNum的數向後移動一格 a[j+1]=a[j];//元素移動一格 j--; } a[j+1]=insertNum;//將需要插入的數放在要插入的位置。 } }

2.希爾排序

對於直接插入排序問題,數據量巨大時。

將數的個數設為n,取奇數k=n/2,將下標差值為k的數分為一組,構成有序序列。再取k=k/2 ,將下標差值為k的書分為一組,構成有序序列。重複第二步,直到k=1執行簡單插入排序。

如何寫成代碼:

首先確定分的組數。然後對組中元素進行插入排序。然後將length/2,重複1,2步,直到length=0為止。代碼實現如下:

public void sheelSort(int[] a){int d = a.length; while (d!=0) { d=d/2; for (int x = 0; x < d; x++) {//分的組數 for (int i = x + d; i < a.length; i += d) {//組中的元素,從第二個數開始 int j = i - d;//j為有序序列最後一位的位數 int temp = a[i];//要插入的元素 for (; j >= 0 && temp < a[j]; j -= d) {//從後往前遍歷。 a[j + d] = a[j];//向後移動d位 } a[j + d] = temp; } } } }

3.簡單選擇排序

常用於取序列中最大最小的幾個數時。

(如果每次比較都交換,那麼就是交換排序;如果每次比較完一個循環再交換,就是簡單選擇排序。)

遍歷整個序列,將最小的數放在最前面。遍歷剩下的序列,將最小的數放在最前面。重複第二步,直到只剩下一個數。

如何寫成代碼:

首先確定循環次數,並且記住當前數字和當前位置。將當前位置後面所有的數與當前數字進行對比,小數賦值給key,並記住小數的位置。比對完成後,將最小的值與第一個數的值交換。重複2、3步。代碼實現如下:

public void selectSort(int[] a) { int length = a.length; for (int i = 0; i < length; i++) {//循環次數 int key = a[i]; int position=i; for (int j = i + 1; j < length; j++) {//選出最小的值和位置 if (a[j] < key) { key = a[j]; position = j; } } a[position]=a[i];//交換位置 a[i]=key; } }

4.堆排序

對簡單選擇排序的優化。

將序列構建成大頂堆。將根節點與最後一個節點交換,然後斷開最後一個節點。重複第一、二步,直到所有節點斷開。

代碼實現如下:

public void heapSort(int[] a){System.out.println("開始排序"); int arrayLength=a.length; //循環建堆 for(int i=0;i<arraylength-1;i++){ //建堆 buildMaxHeap(a,arrayLength-1-i); //交換堆頂和最後一個元素 swap(a,0,arrayLength-1-i); System.out.println(Arrays.toString(a)); } } private void swap(int[] data, int i, int j) { // TODO Auto-generated method stub int tmp=data[i]; data[i]=data[j]; data[j]=tmp; } //對data數組從0到lastIndex建大頂堆 private void buildMaxHeap(int[] data, int lastIndex) { // TODO Auto-generated method stub //從lastIndex處節點(最後一個節點)的父節點開始 for(int i=(lastIndex-1)/2;i>=0;i--){ //k保存正在判斷的節點 int k=i; //如果當前k節點的子節點存在 while(k*2+1<=lastIndex){ //k節點的左子節點的索引 int biggerIndex=2*k+1; //如果biggerIndex小於lastIndex,即biggerIndex+1代表的k節點的右子節點存在 if(biggerIndex<lastindex){ //若果右子節點的值較大 if(data[biggerIndex]<data[biggerindex+1]){ //biggerIndex總是記錄較大子節點的索引 biggerIndex++; } } //如果k節點的值小於其較大的子節點的值 if(data[k]<data[biggerindex]){ //交換他們 swap(data,k,biggerIndex); //將biggerIndex賦予k,開始while循環的下一次循環,重新保證k節點的值大於其左右子節點的值 k=biggerIndex; }else{ break; } } } }

5.冒泡排序

一般不用。

將序列中所有元素兩兩比較,將最大的放在最後面。將剩餘序列中所有元素兩兩比較,將最大的放在最後面。重複第二步,直到只剩下一個數。

如何寫成代碼:

設置循環次數。設置開始比較的位數,和結束的位數。兩兩比較,將最小的放到前面去。重複2、3步,直到循環次數完畢。代碼實現如下:

public void bubbleSort(int[] a){int length=a.length; int temp; for(int i=0;i<a.length;i++){ for(int j=0;j<a.length-i-1;j++){ if(a[j]>a[j+1]){ temp=a[j]; a[j]=a[j+1]; a[j+1]=temp; } } } }

6.快速排序

要求時間最快時。

選擇第一個數為p,小於p的數放在左邊,大於p的數放在右邊。遞歸的將p左邊和右邊的數都按照第一步進行,直到不能遞歸。

代碼實現如下:

public static void quickSort(int[] numbers, int start, int end) { if (start < end) { int base = numbers[start]; // 選定的基準值(第一個數值作為基準值) int temp; // 記錄臨時中間值 int i = start, j = end; do { while ((numbers[i] < base) && (i < end)) i++; while ((numbers[j] > base) && (j > start)) j--; if (i <= j) { temp = numbers[i]; numbers[i] = numbers[j]; numbers[j] = temp; i++; j--; } } while (i <= j); if (start < j) quickSort(numbers, start, j); if (end > i) quickSort(numbers, i, end); } }

7.歸併排序

速度僅次於快排,內存少的時候使用,可以進行並行計算的時候使用。

選擇相鄰兩個數組成一個有序序列。選擇相鄰的兩個有序序列組成一個有序序列。重複第二步,直到全部組成一個有序序列。

代碼實現如下:

public static void mergeSort(int[] numbers, int left, int right) { int t = 1;// 每組元素個數 int size = right - left + 1; while (t < size) { int s = t;// 本次循環每組元素個數 t = 2 * s; int i = left; while (i + (t - 1) < size) { merge(numbers, i, i + (s - 1), i + (t - 1)); i += t; } if (i + (s - 1) < right) merge(numbers, i, i + (s - 1), right); } } private static void merge(int[] data, int p, int q, int r) { int[] B = new int[data.length]; int s = p; int t = q + 1; int k = p; while (s <= q && t <= r) { if (data[s] <= data[t]) { B[k] = data[s]; s++; } else { B[k] = data[t]; t++; } k++; } if (s == q + 1) B[k++] = data[t++]; else B[k++] = data[s++]; for (int i = p; i <= r; i++) data[i] = B[i]; }

8.基數排序

用於大量數,很長的數進行排序時。

將所有的數的個位數取出,按照個位數進行排序,構成一個序列。將新構成的所有的數的十位數取出,按照十位數進行排序,構成一個序列。

代碼實現如下:

public void sort(int[] array) {//首先確定排序的趟數; int max = array[0]; for (int i = 1; i < array.length; i++) { if (array[i] > max) { max = array[i]; } } int time = 0; //判斷位數; while (max > 0) { max /= 10; time++; } //建立10個隊列; List queue = new ArrayList(); for (int i = 0; i < 10; i++) { ArrayList queue1 = new ArrayList(); queue.add(queue1); } //進行time次分配和收集; for (int i = 0; i < time; i++) { //分配數組元素; for (int j = 0; j < array.length; j++) { //得到數字的第time+1位數; int x = array[j] % (int) Math.pow(10, i + 1) / (int) Math.pow(10, i); ArrayList queue2 = queue.get(x); queue2.add(array[j]); queue.set(x, queue2); } int count = 0;//元素計數器; //收集隊列元素; for (int k = 0; k < 10; k++) { while (queue.get(k).size() > 0) { ArrayList queue3 = queue.get(k); array[count] = queue3.get(0); queue3.remove(0); count++; } } } }

相關焦點

  • Java實現冒泡排序算法
    學習方法推薦:#學習方法1.從基礎開始,系統化學習2.多動手,每一種數據結構與算法,都自己用代碼實現出來3.思路更重要:理解實現思想,不要背代碼4.與日常開發結合,對應應用場景>2.考考你在上一篇:數據結構與算法系列十(排序概述)中,我們列舉了常用的排序算法,以及分析了如何綜合衡量排序算法的優劣。
  • 2020年的Java程式設計師面試三件套:多線程+算法+微服務
    該模式也可以防止實例不一致。通過本章還可以練習Java語言中的wait方法和notifyAll方法的使用。本章還將給出阻塞隊列java.util.concurrent.LinkedBlockingQueue的示例程序。
  • Java基礎面試題簡單總結
    Collections是針對集合類的一個幫助類,他提供一系列靜態方法實現對各種集合的搜索、排序、線程安全化等操作6、什麼時候用assert答:assertion(斷言)在軟體開發中是一種常用的調試方式,很多開發語言中都支持這種機制。
  • 程式設計師必備的幾種常見排序算法和搜索算法總結
    .在真實項目中我們往往不會採用冒泡排序,更多的會用快速排序或者希爾排序.關於排序算法性能問題我在《前端算法系列》如何讓前端代碼速度提高60倍有詳細介紹.接下來就讓我們來一起學習如何實現文章開頭的幾個常用排序和搜索算法吧.1. 冒泡排序及其優化我們在學排序算法時, 最容易掌握的就是冒泡排序, 因為其實現起來非常簡單,但是從運行性能的角度來看, 它卻是性能最差的一個.
  • Arrays.sort() 為什麼可以對 int 等數組進行排序?我跟面試官扯了...
    作者 | TrueDei責編 | 王曉曼出品 | CSDN博客前言排序是在程序開發中最常用到的,最常見的就是針對一些數字進行排序。而現實中像商品的名字,訂單的日期等進行排序。Java的JDK中就自帶了Comparable接口,那麼來看下這個,如何與面試官對答如流。
  • 五大常用算法:一文搞懂分治算法
    原創公眾號:bigsai文章收錄在 bigsai-algorithm前言分治算法(divide and conquer)是五大常用算法(分治算法、動態規划算法、貪心算法、回溯法、分治界限法)之一,很多人在平時學習中可能只是知道分治算法,但是可能並沒有系統的學習分治算法
  • 我們到底該如何學習《數據結構與算法》
    凡是大家知道的那些大廠基本上上來就是先敲代碼。可以看出國內外大廠對於算法與數據結構的看重。第二:工作現在的大廠api框架基本上背後的邏輯就是基於算法實現的。其實算法的種類有很多,比如說機器學習、神經網絡算法,還有java中的排序算法,網際網路的商品推薦、股票預測其背後的邏輯都是算法。
  • 看動畫學算法之:排序-冒泡排序
    簡介排序可能是所有的算法中最最基礎和最最常用的了。排序是一個非常經典的問題,它以一定的順序對一個數組(或一個列表)中的項進行重新排序。排序算法有很多種,每個都有其自身的優點和局限性。今天我們來學習最最簡單的冒泡排序算法。
  • 5分鐘弄懂的五大常用算法之「分治法」,以C語言歸併排序算法為例
    分治算法,顧名思義就是「分而治之」,即把規模較大的複雜問題拆分為若干規模較小的類似子問題,並逐個解決,最後再將各個子問題的解決結果合併,得到原始問題的結果的方法。這個技巧是很多高效算法的基礎,例如快速排序算法、歸併排序算法、快速傅立葉變換等等。
  • Java的synchronized 能防止指令重排序嗎?
    「二胖」:基礎太差,一面就讓回去等通知了,我要好好學習了,不跟你瞎扯了。「二狗:」 都問了你什麼問題啊,把你打擊成這樣?一起復盤下讓我也好好準備下啊。「二胖」:好吧,你既然這麼好奇,那我就大概說下吧,你搬上小板凳仔細挺好了哦。我要開始我的表演了。下面二胖第一面開始了。「面試官」:二胖是吧,先做個自我介紹吧。
  • Github標星42K+超火的幾份算法筆記寶典,刷新了我對算法的新認知
    &(邏輯與)、| (邏輯或)和^(異或)五種字符組成的字符串express再給定一個布爾值desired.返回express能有多少種組合方式,可以達到desired的結果。給定一個字符串數組strs[],在strs中有些位置為null,但在不為null的位置上,其字符串是按照字典順序由小到大依次出現的。
  • 年初離職,學習半年源碼,終於拿到了螞蟻Offer,分享面試過程
    小夥伴從去年開始,一直叨叨要跳槽,大大小小的公司面試了很多,但總沒有拿到一個滿意的offer,要麼package太低,要麼就是面試被虐。經過前幾次的面試失利,終於明白了什麼叫基礎不牢,地動山搖。面試官隨便針對一個知識點深入考察一下,就回答不出來,就這樣,還怎麼能通過面試?不過,最近收到了小夥伴的捷報,已拿到阿里的offer,公司足夠大,base還可以,雖然是個P6,但還是隱隱感覺到他很滿意。其實,我還是有點疑惑,他之前的基礎很一般,咋就突然拿到了阿里的offer。
  • Python中的快速排序算法,快速排序的優缺點,中級python技術點
    在Python中實現Quicksort這是quicksort的一個相當緊湊的實現:以下是代碼摘要:如果數組包含的元素少於兩個,第6行將停止遞歸函數。選擇主元為什麼上面的實現會隨機選擇主元素?一致地選擇輸入列表的第一個或最後一個元素不是同樣的嗎?由於快速排序算法的工作方式,遞歸層的數量取決於主元在每個分區中的位置。在最佳情況下,算法始終選擇中位數元素作為軸心。
  • 公司來了一位前阿里大神,分享8面阿里面經(Java崗面試題集錦)
    說在最開頭:說一下最近幾次面試大廠的經歷,害,一言難盡,都讓我覺得自己近期兩個多月都沒有學到東西,問的問題要說深入底層也深入了,但是你說是基礎嗎,其實也是,但就是沒有回答好,這跟自己面試技巧也有關係吧,不會展現自己,也不會引導面試官,去展示自己的長處。
  • 2020年6月最新BAT一線大廠JAVA崗高頻面試題:阿里+華為+字節跳動
    13.知道spring AOP是如何實現的麼,動態代理和CGlib分別是如何實現的14.了解Dubbo框架不,看過源碼沒,了解實現原理嗎?15.給定一個整數數組和一個整數,返回兩個數組的索引,這兩個索引指向的數字的加和等於指定的整數。
  • 2020學習Java必看的3本書籍
    《Effective Java》本書一共包含90個條目,每個條目討論Java程序設計中的一條規則。這些規則反映了最有經驗的優秀程式設計師在實踐中常用的一些有益的做法。本書的目標是幫助讀者更加有效地使用Java程式語言及其基本類庫:java.lang、java.util和java.io,以及子包,如java.util.concurrent和java.util.function。本書時不時地也會討論其他的類庫。3.
  • 2021年金三銀四跳槽必備對標阿里P5的685集java就業班全套視頻
    在隔離的這段時間,小編就給大家準備了金三銀四跳槽必備的685集java就業班教程視頻來學習,希望大家能夠喜歡!!113_IDEA的常用快捷鍵214_代碼模板是什麼15_常用代碼模板16_修改代碼模板17_創建代碼模板18_斷點調試_常用斷點調試快捷鍵19_斷點調試_條件判斷20_斷點調試_查看表達式值21_創建JavaWeb項目22_在IDEA中添加Tomcat的鏡像
  • 「讀書筆記」《漫畫算法》:克服對算法的恐懼,從漫畫開始
    如果我說這本書的大部分內容(我不負責任的粗略估計大概有60%)都是對公眾號文章的重製版,不知道大家會不會有點失望呢。當然,在書中,內容的順序是經過仔細編排的。書裡從算法和數據結構的定義和概念說起,再到時間空間複雜度的介紹,到數據結構基礎,比如數組,鍊表,隊列。最後才是一些具體的算法問題。
  • Java單循環直接選擇排序算法
    通過此for循環模擬經典直接選擇排序法中的內循環。(2)經典直接選擇選擇排序法中的外循環實際上就是一個計數器,我們在一個循環裡就可以做到,而不必另外再外嵌套一個循環。二.實戰演示:(1)先創建一個數組並初始化:(2)遍歷並顯示排序前的數組:(3)創建for循環:for循環效果演示:說明:實戰演示中,我們發現最後兩位是在循環結束後形成的
  • 數據結構java面試題及答案
    數組是最常用的基礎數據結構,它將元素保存在連續的內存中。它也是面試最喜歡的問題之一,在代碼面試中你會經常聽到很多關於數組的問題,例如,數組的反轉、數組的排序或者查找數組中的一個元素。數組結構的一個關鍵優點是在知道索引的情況能夠以O(1)的複雜度找到一個元素。但是增加或者刪除一個元素是很慢的,因為一旦創建了一個數組,你就不能改變它的大小了。