柚子快報激活碼778899分享:八大排序算法(面試被問到)
柚子快報激活碼778899分享:八大排序算法(面試被問到)
1.八大排序算法都是什么?
八大排序算法有:插入排序、冒泡排序、歸并排序、選擇排序、快速排序、希爾排序、堆排序、基數(shù)排序(通常不提)。此外,還可以直接調(diào)用Arrays.sort()進(jìn)行排序。
2.八大排序算法時間復(fù)雜度和穩(wěn)定性?
這里有一個口訣記法:
插(插入)帽(冒泡)龜(歸并),他很穩(wěn)(穩(wěn)定);
插冒歸喜歡選(選擇)插(插入)帽(冒泡),插完他就方了O(n^2);
快(快速)歸(歸并)隊(堆),n老O(logn);
基(基數(shù))你太穩(wěn)(穩(wěn)定);
3.算法講解?
? (1) 冒泡排序
過程:
①從數(shù)列的開頭開始,在這趟遍歷中對沒有進(jìn)行比較的一對兩兩比較,直到數(shù)列的結(jié)尾;
②如果第一個元素比第二個元素大,則交換它們的位置,這樣較大的元素就逐漸“浮”到數(shù)列的末尾;
③然后,算法再次從數(shù)列的開始執(zhí)行相同的操作,但是排好序的元素(即最大的元素)不再參與比較;這個過程一直持續(xù)到整個數(shù)列都排好序為止。
代碼實現(xiàn):
public class BubbleSort {
11 public static void main(String[] args) {
12 int[] arr={5,4,2,1};
13 bubblesort(arr);
14 System.out.println("Sorted array:"+ Arrays.toString(arr));
15 for(int i=0;i 16 System.out.print(arr[i]+" "); 17 } 18 } 19 20 private static void bubblesort(int[] arr) { 21 int n=arr.length; 22 for(int i=0;i 23 for(int j=0;j 24 if(arr[j]>arr[j+1]){ 25 int temp=arr[j]; 26 arr[j]=arr[j+1]; 27 arr[j+1]=temp; 28 } 29 } 30 } 31 } 34 } 優(yōu)點: 穩(wěn)定性——在排序過程中,相同元素的相對順序保持不變。 缺點: 不適合大規(guī)模數(shù)據(jù)——對于大規(guī)模亂序序列的排序效率較低,時間復(fù)雜度較高。 (2)插入排序 過程: ?①將第一個元素視為已排序序列。 ②從第二個元素開始,將其與已排序序列中的元素逐個比較,并插入到正確的位置上。這個過程不斷重復(fù),直到整個數(shù)組變得有序。 ③在實現(xiàn)上,插入排序使用雙層循環(huán),外層循環(huán)遍歷數(shù)組中的每個元素,內(nèi)層循環(huán)則在已排序的部分中查找新元素應(yīng)插入的位置。 代碼實現(xiàn): public class InsertSort { 11 public static void main(String[] args) { 12 int[] arr={23,46,87,11,24,1}; 13 System.out.println("Original array:"+ Arrays.toString(arr)); 14 insertsort(arr); 15 System.out.println("Sorted array:"+Arrays.toString(arr)); 16 for(int i=0;i 17 System.out.print(arr[i]+" "); 18 } 19 } 20 public static void insertsort(int[] arr){ 21 //遍歷除第一個數(shù)之外的所有數(shù)字 22 for(int i=1;i 23 //當(dāng)前數(shù)字比前一個數(shù)字小 24 if(arr[i] 25 //把當(dāng)前數(shù)字保存起來,當(dāng)前位置騰開 26 int temp=arr[i]; 27 //當(dāng)前數(shù)字和他之前所有數(shù)字進(jìn)行比較 28 int j=0; 29 for(j=i-1;j>=0&&arr[j]>temp;j--){//如果前面的數(shù)字大于temp,右移 30 arr[j+1]=arr[j]; 31 } 32 arr[j+1]=temp;//如果前面的數(shù)字小于等于temp,將temp放入 33 } 34 } 35 } 36 37 } 優(yōu)點: 穩(wěn)定性——在排序過程中,相同元素的相對順序保持不變。 缺點: 不適合大規(guī)模數(shù)據(jù)——對于大規(guī)模亂序序列的排序效率較低,時間復(fù)雜度較高。 (3)歸并排序 過程: ①分解(Divide):將數(shù)組遞歸地分成兩半,直到數(shù)組被分解為單個元素。 ②解決(Conquer):對每一對分解后的子數(shù)組進(jìn)行排序,這一過程通常通過歸并排序遞歸地完成。 ③合并(Merge):將已排序的子數(shù)組合并成一個完整的、有序的數(shù)組。 代碼實現(xiàn): public class MergeSort { 11 public static void main(String[] args) { 12 int[] arr={12,11,13,43,5,9}; 13 System.out.println("Original Array:"+ Arrays.toString(arr)); 14 mergesort(arr,0,arr.length-1); 15 System.out.println("Sorted Array:"+Arrays.toString(arr)); 16 } 17 18 private static void mergesort(int[] arr,int left,int right) { 19 if(left 20 int mid=(left + right) / 2; 21 mergesort(arr,left,mid); 22 mergesort(arr,mid+1,right); 23 Merge(arr,left,mid,right); 24 } 25 26 } 27 28 private static void Merge(int[] arr, int left, int mid, int right) { 29 int i=left;int j=mid+1;int k=0; 30 int[] temp=new int[right-left+1]; 31 while(i<=mid&&j<=right){ 32 if(arr[i] 33 temp[k++]=arr[i++]; 34 }else{ 35 temp[k++]=arr[j++]; 36 } 37 } 38 while(i<=mid){ 39 temp[k++]=arr[i++]; 40 } 41 while(j<=right){ 42 temp[k++]=arr[j++]; 43 } 44 //按照排好的順序給arr賦值 45 for(int t=0;t 46 arr[t+left]=temp[t]; 47 } 48 } 49 } 優(yōu)點: 穩(wěn)定性——在排序過程中,相同元素的相對順序保持不變。 缺點: 內(nèi)存占用大——在劃分和合并過程中,需要額外的內(nèi)存來存儲列表的兩半和最終排序的列表, (4)選擇排序 過程: ①從待排序的數(shù)據(jù)元素中選出最?。ɑ蜃畲螅┑囊粋€元素,存放在序列的起始位置; ②再從剩余的未排序元素中繼續(xù)尋找最小(或最大)元素,然后放到已排序序列的末尾; ③重復(fù)操作,直到所有元素均排序完畢。 代碼實現(xiàn): public class SelectSort { 11 public static void main(String[] args) { 12 int[] arr={12,45,72,32,10}; 13 System.out.println("Original Array:"+ Arrays.toString(arr)); 14 insertsort(arr); 15 System.out.println("Sorted Array:"+Arrays.toString(arr)); 16 for(int i=0;i 17 System.out.print(arr[i]+" "); 18 } 19 } 20 public static void insertsort(int[] arr){ 21 int n=arr.length; 22 for(int k=0;k 23 int min=k;//設(shè)置第一個下標(biāo)為最小值 24 for(int i=k+1;i 25 if(arr[i] 26 min=i;//更新最小值對應(yīng)的下標(biāo) 27 } 28 } 29 int temp=arr[k];//交換,將最小值標(biāo)記到最前面,之后k++,尋找第二個最小值,循環(huán) 30 arr[k]=arr[min]; 31 arr[min]=temp; 32 } 33 } 35 } 優(yōu)點: 可讀性高——簡單易懂、易于實現(xiàn),以及它是原地排序算法,不占用額外的內(nèi)存空間。 缺點: 時間復(fù)雜度較高——無論數(shù)據(jù)是否有序,都需要進(jìn)行O(n2)次比較,處理大規(guī)模數(shù)據(jù)集時效率較低。 不穩(wěn)定——這意味著在排序過程中相等元素的相對位置可能發(fā)生變化,導(dǎo)致相同元素的相對順序不同。 (5)快速排序 過程: ①選擇基準(zhǔn)元素:從待排序序列中選取一個元素作為基準(zhǔn)(pivot)。 ②分區(qū)操作:通過比較其他元素與基準(zhǔn)元素的大小,將序列分為兩部分。所有比基準(zhǔn)元素小的元素放在其左邊,所有比基準(zhǔn)元素大的元素放在其右邊。 ③遞歸排序:對基準(zhǔn)元素左右兩邊的子序列遞歸執(zhí)行上述步驟,直到子序列的長度為0或1,此時子序列已經(jīng)有序。 代碼實現(xiàn): public class QuickSort { 11 //快速排序: 12 //首先在序列中隨機(jī)選擇一個基準(zhǔn)值(privot) 13 //除了基準(zhǔn)值以外的數(shù)分為:“比基準(zhǔn)值小的數(shù)”、“比基準(zhǔn)值大的數(shù)”,再將其排列成以下形式 【比基準(zhǔn)值小的數(shù)】 基準(zhǔn)值 【比基準(zhǔn)值大的數(shù)】 14 //對【】中的數(shù)據(jù)進(jìn)行遞歸,同樣使用快速排序 15 public static void main(String[] args) { 16 int[] arr={12,45,67,81,1,2}; 17 System.out.println("Original array:"+ Arrays.toString(arr)); 18 quicksort(arr,0,arr.length-1); 19 System.out.println("Sorted array:"+Arrays.toString(arr)); 20 for(int i=0;i 21 System.out.print(arr[i]+" "); 22 } 23 } 24 public static void quicksort(int[] arr,int left,int right){ 25 if(left 26 int partitionIndex=partition(arr,left,right); 27 quicksort(arr,left,partitionIndex-1); 28 quicksort(arr,partitionIndex+1,right); 29 } 30 } 31 public static int partition(int[] arr,int left,int right) { 32 int privot=arr[left]; 33 while(left 34 while(left 35 right--; 36 } 37 arr[left]=arr[right]; 38 while(left 39 left++; 40 } 41 arr[right]=arr[left]; 42 } 43 //在left==right時候,將privot放進(jìn)去,此時privot左邊都是比privot小的,privot右邊都是比privot大的 44 arr[left]=privot; 45 return left; 46 } 47 } 優(yōu)點: 高效率——快速排序的平均時間復(fù)雜度為O(NlogN),使其在處理大量數(shù)據(jù)時表現(xiàn)出色。 數(shù)據(jù)移動少——在排序過程中,快速排序需要移動的數(shù)據(jù)量相對較小。 缺點: 不穩(wěn)定——當(dāng)處理大量重復(fù)元素時,可能會導(dǎo)致遞歸深度過大,甚至棧溢出。 (6)堆排序 過程: ①最大堆調(diào)整(Max Heapify):將堆的末端子節(jié)點作調(diào)整,使得子節(jié)點永遠(yuǎn)小于父節(jié)點; ②創(chuàng)建最大堆(Build Max Heap):將堆中的所有數(shù)據(jù)重新排序(按照最大堆調(diào)整); ③堆排序(HeapSort):移除位在第一個數(shù)據(jù)的根節(jié)點(最大堆順序就會被打亂),并重復(fù)做最大堆調(diào)整的遞歸運算。 代碼實現(xiàn): public class HeapSort { 11 //大頂堆: 12 // 孩子節(jié)點下標(biāo)為i時,父節(jié)點下標(biāo):(i-1)/2 13 //父親節(jié)點下標(biāo)為k時,左孩子下標(biāo)(k*2)+1;右孩子下標(biāo)k*2+2 14 public static void main(String[] args) { 15 //測試用例 16 int[] arr={12,45,72,32,10}; 17 System.out.println("Original Array:"+ Arrays.toString(arr)); 18 heapsort(arr); 19 System.out.println("Sorted Array:"+Arrays.toString(arr)); 20 for(int k:arr){ 21 System.out.print(k+" "); 22 } 23 } 24 25 //堆排序函數(shù) 26 private static void heapsort(int[] arr) { 27 int n=arr.length; 28 //建堆 29 buildMaxHeap(arr,n); 30 for(int i=n-1;i>0;i--){ 31 //交換 32 swap(arr,0,i); 33 //維護(hù)最大堆的性質(zhì) 34 heapify(arr,0,i); 35 } 36 // 37 } 38 39 private static void heapify(int[] arr, int x, int n) { 40 int father=x; 41 int left=2*x+1; 42 int right=2*x+2; 43 if(left 44 father=left; 45 } 46 if(right 47 father=right; 48 } 49 if(father!=x){ 50 swap(arr,x,father); 51 heapify(arr,father,n);//向下調(diào)整維護(hù)大堆性質(zhì) 52 } 53 54 } 55 56 private static void swap(int[] arr, int a, int b) { 57 int temp=arr[a]; 58 arr[a]=arr[b]; 59 arr[b]=temp; 60 } 61 62 private static void buildMaxHeap(int[] arr, int n) { 63 //尋找最后一個非葉子節(jié)點 64 for(int i=n/2-1;i>=0;i--){ 65 heapify(arr,i,n); 66 } 67 } 68 } 優(yōu)點: 速度快——時間復(fù)雜度為O(nlogn),這意味著無論數(shù)據(jù)規(guī)模多大,堆排序都能在多項式時間內(nèi)完成。排序空間復(fù)雜度O(1),這意味著它不需要額外的存儲空間來保存數(shù)據(jù),這使得堆排序在空間效率方面表現(xiàn)優(yōu)異; 穩(wěn)定——堆排序是一種穩(wěn)定的排序算法,堆排序適用于多種場景,包括在數(shù)據(jù)頻繁變動的情況下,因為它可以在不重建整個堆的情況下更新堆頂元素。 缺點: 堆維護(hù)問題——需要頻繁地重建和維護(hù)堆,這可能會在數(shù)據(jù)頻繁變動的情況下導(dǎo)致效率降低,因為每次數(shù)據(jù)更新都可能需要調(diào)整堆的結(jié)構(gòu),這增加了額外的計算負(fù)擔(dān)。 (7)希爾排序 希爾排序是一種改進(jìn)后的插入排序算法,也被稱為縮小增量排序。 過程: ①選擇一個小于數(shù)組長度的增量(gap),最開始gap=n/2,然后將數(shù)組分為多個子序列,每個子序列的元素間隔為這個增量值,對每個子序列分別進(jìn)行直接插入排序。 ②逐漸減小增量值(減半),再次進(jìn)行子序列的劃分和排序。 ③直到增量減至1,此時整個數(shù)組被當(dāng)作一個序列進(jìn)行插入排序。 代碼實現(xiàn): public class ShellSort { 11 public static void main(String[] args) { 12 int[] arr=new int[]{12,23,11,5,65,88}; 13 System.out.println("Original Array:"+ Arrays.toString(arr)); 14 shellsort(arr); 15 System.out.println("Sorted Array:"+Arrays.toString(arr)); 16 for(int i=0;i 17 System.out.print(arr[i]+" "); 18 } 19 } 20 21 private static void shellsort(int[] arr) {//時間復(fù)雜度n^1.3 22 int n=arr.length; 23 //初始化間隔為數(shù)組長度的一半 24 int gap=n/2; 25 while(gap>0){ 26 //對每個間隔進(jìn)行直接插入排序 27 for(int i=gap;i 28 int temp=arr[i]; 29 int j=0; 30 //對間隔為 gap 的元素進(jìn)行插入排序 31 for(j=i;j>=gap&&temp 32 arr[j]=arr[j-gap]; 33 } 34 arr[j]=temp; 35 } 36 // 縮小間隔 37 gap=gap/2; 38 } 39 } 40 } 優(yōu)點: 速度快——由于開始時增量的取值較大,每個子序列中的元素較少,所以排序速度快;隨著增量逐漸減小,雖然子序列中的元素個數(shù)增多,但是由于前面工作的基礎(chǔ),大多數(shù)元素已經(jīng)基本有序,因此排序速度仍然較快。希爾排序的時間復(fù)雜度為O(n^1.3)至O(n^2)。 缺點: 不穩(wěn)定——取決于增量序列的選擇,它是一種非穩(wěn)定排序算法,這意味著在排序過程中,相同的元素可能會移動位置,導(dǎo)致最終順序與原始順序不同。 柚子快報激活碼778899分享:八大排序算法(面試被問到) 文章來源
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。
轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。