欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java數(shù)據(jù)結(jié)構(gòu)之基于比較的排序算法基本原理及具體實(shí)現(xiàn)

 更新時(shí)間:2021年09月26日 09:22:15   作者:信仰xinyang  
最近剛學(xué)習(xí)完七種比較常見(jiàn)的基于比較的排序算法,感覺(jué)比較重要,所以寫(xiě)個(gè)博客記錄一下,通讀本篇對(duì)大家的學(xué)習(xí)或工作具有一定的價(jià)值,需要的朋友可以參考下

基于比較的排序算法基本原理及Java實(shí)現(xiàn)

1. 七大基于比較的排序-總覽

1.1常見(jiàn)基于比較的排序分類(lèi)

在這里插入圖片描述

1.2時(shí)間復(fù)雜度,空間復(fù)雜度以及穩(wěn)定性。

  • 穩(wěn)定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面。
  • 不穩(wěn)定:如果a原本在b的前面,而a=b,排序之后 a 可能會(huì)出現(xiàn)在 b 的后面。

2.直接插入排序

2.1 直接插入排序的基本思想

直接插入排序的基本思想,就是每次選取一個(gè)待排序元素,按照一定規(guī)定插入到前面已經(jīng)排好序的一組元素的適當(dāng)位置。當(dāng)每個(gè)元素都插入完畢,整個(gè)序列已經(jīng)有序。

當(dāng)插入第i(i >= 1)時(shí),前面的V[0],V[1],……,V[i-1]已經(jīng)排好序。這時(shí),用V[I]的排序碼與V[i-1],V[i-2],…的排序碼順序進(jìn)行比較,找到插入位置即將V[i]插入,原來(lái)位置上的元素向后順移。

2.2 直接插入排序動(dòng)畫(huà)演示

在這里插入圖片描述

2.3 代碼示例

public static void insertSort(int[] arr){
        for(int i=1;i<arr.length;i++){//從第二個(gè)元素開(kāi)始,遍歷整個(gè)數(shù)組
            int j=i-1;//i之前的序列 已經(jīng)有序
            int temp=arr[i];
            for(;j>=0;j--){//此循環(huán)用于尋找插入位置
                if(arr[j]>temp){//此時(shí)逐個(gè)向后移動(dòng)元素
                    arr[j+1]=arr[j];
                }else break;//找到插入位置 直接break
            }
            arr[j+1]=temp;//直接插入
        }
}

2.4 時(shí)間復(fù)雜度,空間復(fù)雜度以及穩(wěn)定性

  • 時(shí)間復(fù)雜度最壞情況:數(shù)組整體逆序O(n^2);
  • 時(shí)間復(fù)雜度最好情況:數(shù)組已經(jīng)有序O(n^2);
  • 空間復(fù)雜度:O(1);
  • 穩(wěn)定性:穩(wěn)定;

3. 希爾排序

3.1 算法思想

希爾排序是特殊的插入排序,直接插入排序每次插入前的遍歷步長(zhǎng)為1,而希爾排序是將待排序列分為若干個(gè)子序列,對(duì)這些子序列分別進(jìn)行直接插入排序,當(dāng)每個(gè)子序列長(zhǎng)度為1時(shí),再進(jìn)行一次直接插入排序時(shí),結(jié)果一定是有序的。常見(jiàn)的劃分子序列的方法有:初始步長(zhǎng)(兩個(gè)子序列相應(yīng)元素相差的距離)為要排的數(shù)的一半,之后每執(zhí)行一次步長(zhǎng)折半。

3.2 圖片演示

3.3 代碼示例

public static void hell(int[] arr,int gap){//當(dāng)gap=1時(shí) 其實(shí)就是直接插入排序
        for(int i=gap;i<arr.length;i++){
            int j=i-gap;
            int temp=arr[i];
            for(;j>=0;j-=gap){
                if(arr[j]>temp){
                    arr[j+gap]=arr[j];
                }else break;
            }
            arr[j+gap]=temp;
        }
}
public static void hellSort(int[] arr){
        int gap=arr.length;
        while(gap>1){
            gap=gap/2+1;
            hell(arr,gap);
        }
    }

3.4 時(shí)間復(fù)雜度,空間復(fù)雜度以及穩(wěn)定性

  • 時(shí)間復(fù)雜度最好:O(n);
  • 時(shí)間復(fù)雜度最壞:O(n^1.5);
  • 時(shí)間復(fù)雜度平均:O(n^1.3);
  • 空間復(fù)雜度:O(1);
  • 穩(wěn)定性:不穩(wěn)定;

4.選擇排序

4.1 算法思想

選擇排序(Selection-sort)是一種簡(jiǎn)單直觀(guān)的排序算法。它的工作原理:首先在未排序序列中找到最?。ù螅┰?,存放到排序序列的起始位置,然后,再?gòu)氖S辔磁判蛟刂欣^續(xù)尋找最小(大)元素,然后放到已排序序列的末尾。以此類(lèi)推,直到所有元素均排序完畢。

4.2 動(dòng)畫(huà)演示

img

4.3 代碼示例

public static void selectSort(int[] arr){
        for(int i=0;i<arr.length;i++){
            for(int j=i+1;j<arr.length;j++){
                if(arr[j]<arr[i]){
                    int temp=arr[j];
                    arr[j]=arr[i];
                    arr[i]=temp;
                }
            }
      }
}

4.4 時(shí)間復(fù)雜度,空間復(fù)雜度以及穩(wěn)定性

  • 時(shí)間復(fù)雜度最好:O(n);
  • 時(shí)間復(fù)雜度最壞:O(n^2;
  • 時(shí)間復(fù)雜度平均:O(n^2);
  • 空間復(fù)雜度:O(1);
  • 穩(wěn)定性:不穩(wěn)定;

5.堆排序

5.1 算法思想

堆是具有以下性質(zhì)的完全二叉樹(shù):每個(gè)結(jié)點(diǎn)的值都大于或等于其左右孩子結(jié)點(diǎn)的值,稱(chēng)為大頂堆;或者每個(gè)結(jié)點(diǎn)的值都小于或等于其左右孩子結(jié)點(diǎn)的值,稱(chēng)為小頂堆。如下圖:

  • 將初始待排序關(guān)鍵字序列(R1,R2….Rn)構(gòu)建成大頂堆,此堆為初始的無(wú)序區(qū);
  • 將堆頂元素R[1]與最后一個(gè)元素R[n]交換,此時(shí)得到新的無(wú)序區(qū)(R1,R2,……Rn-1)和新的有序區(qū)(Rn),且滿(mǎn)足R[1,2…n-1]<=R[n];
  • 由于交換后新的堆頂R[1]可能違反堆的性質(zhì),因此需要對(duì)當(dāng)前無(wú)序區(qū)(R1,R2,……Rn-1)調(diào)整為新堆,然后再次將R[1]與無(wú)序區(qū)最后一個(gè)元素交換,得到新的無(wú)序區(qū)(R1,R2….Rn-2)和新的有序區(qū)(Rn-1,Rn)。不斷重復(fù)此過(guò)程直到有序區(qū)的元素個(gè)數(shù)為n-1,則整個(gè)排序過(guò)程完成。

img

5.2 動(dòng)畫(huà)演示

img

5.3 代碼示例

public static void heapSort(int[] arr){//排序方法
        creatHeap(arr);
        int end=arr.length-1;
    //因?yàn)槭谴蟾?,所以根?jié)點(diǎn)值為最大值,根節(jié)點(diǎn)與最后一個(gè)節(jié)點(diǎn)值交換 輸出并刪除此時(shí)最后一個(gè)節(jié)點(diǎn),然后向下調(diào)整根節(jié)點(diǎn)
        while(end>0){
            int temp=arr[0];
            arr[0]=arr[end];
            arr[end]=temp;
            shiftDown(arr,0,end);
            end--;
        }

    }
public static void creatHeap(int[] arr){//建堆
        for(int parent=(arr.length-1-1)/2;parent>=0;parent--){
            shiftDown(arr,parent,arr.length);
        }
    }
public static void shiftDown(int[]arr,int root,int len){//向下調(diào)整操作
        int parent=root;
        int child=parent*2+1;
        while(child<len){
            if(child+1<len&&arr[child]<arr[child+1]){//待調(diào)整節(jié)點(diǎn)右子樹(shù)大于左子樹(shù)
                child++;
            }
            if(arr[child]>arr[parent]){//由于是大根堆,如果兒子節(jié)點(diǎn)值大于父親節(jié)點(diǎn)就交換
                int temp=arr[parent];
                arr[parent]=arr[child];
                arr[child]=temp;
                parent=child;//繼續(xù)向下調(diào)整,防止調(diào)整后不滿(mǎn)足大根堆的條件
                child=parent*2+1;
            }else break;
        }
    }

5.4 時(shí)間復(fù)雜度,空間復(fù)雜度以及穩(wěn)定性

  • 時(shí)間復(fù)雜度最好:O(nlogn);
  • 時(shí)間復(fù)雜度最壞:O(nlogn);
  • 時(shí)間復(fù)雜度平均:O(nlogn);
  • 空間復(fù)雜度:O(1);
  • 穩(wěn)定性:不穩(wěn)定;

6.冒泡排序

6.1 算法思想

比較兩個(gè)相鄰的元素,將值大的元素交換到右邊

思路:依次比較相鄰的兩個(gè)數(shù),將比較小的數(shù)放在前面,比較大的數(shù)放在后面。

  • 1.第一次比較:首先比較第一和第二個(gè)數(shù),將小數(shù)放在前面,將大數(shù)放在后面。
  • 2.比較第2和第3個(gè)數(shù),將小數(shù) 放在前面,大數(shù)放在后面。
  • 3.如此繼續(xù),知道比較到最后的兩個(gè)數(shù),將小數(shù)放在前面,大數(shù)放在后面,重復(fù)步驟,直至全部排序完成
  • 4.在上面一趟比較完成后,最后一個(gè)數(shù)一定是數(shù)組中最大的一個(gè)數(shù),所以在比較第二趟的時(shí)候,最后一個(gè)數(shù)是不參加比較的。
  • 5.在第二趟比較完成后,倒數(shù)第二個(gè)數(shù)也一定是數(shù)組中倒數(shù)第二大數(shù),所以在第三趟的比較中,最后兩個(gè)數(shù)是不參與比較的。
  • 6.依次類(lèi)推,每一趟比較次數(shù)減少依次

6.2 動(dòng)畫(huà)演示

img

6.3 代碼示例

public static void bubbleSort(int[] arr){
        for(int i=0;i<arr.length-1;i++){//外層循環(huán)控制趟數(shù)
            boolean flag=false;//一個(gè)標(biāo)記進(jìn)行優(yōu)化
            for(int j=0;j<arr.length-1-i;j++){//內(nèi)層循環(huán)控制比較次數(shù)
                if(arr[j]>arr[j+1]){
                    int temp=arr[j];
                    arr[j]=arr[j+1];
                    arr[j+1]=temp;
                    flag=true;
                }
            }
            if(flag==false) break;//如果一趟循環(huán)走完沒(méi)有交換,說(shuō)明已經(jīng)有序,直接break
        }
    }

6.4 時(shí)間復(fù)雜度,空間復(fù)雜度以及穩(wěn)定性

  • 時(shí)間復(fù)雜度最好:O(n);
  • 時(shí)間復(fù)雜度最壞:O(n^2);
  • 時(shí)間復(fù)雜度平均:O(n^2);
  • 空間復(fù)雜度:O(1);
  • 穩(wěn)定性:穩(wěn)定

7.快速排序(十分重要)

7.1 算法思想

我們從數(shù)組中選擇一個(gè)元素,我們把這個(gè)元素稱(chēng)之為中軸元素吧,然后把數(shù)組中所有小于中軸元素的元素放在其左邊,所有大于或等于中軸元素的元素放在其右邊,顯然,此時(shí)中軸元素所處的位置的是有序的。也就是說(shuō),我們無(wú)需再移動(dòng)中軸元素的位置。

從中軸元素那里開(kāi)始把大的數(shù)組切割成兩個(gè)小的數(shù)組(兩個(gè)數(shù)組都不包含中軸元素),接著我們通過(guò)遞歸的方式,讓中軸元素左邊的數(shù)組和右邊的數(shù)組也重復(fù)同樣的操作,直到數(shù)組的大小為1,此時(shí)每個(gè)元素都處于有序的位置。

7.2 動(dòng)畫(huà)演示

img

7.3 代碼示例

//該代碼參考acwing創(chuàng)始人yxc的快排模板
public static void quickSort(int[] arr,int l,int r){
        if(l>=r) return;//每次判斷傳進(jìn)來(lái)左右下標(biāo)
        int i=l-1,j=r+1;//因?yàn)樵谘h(huán)中,要先i++,j--所以i,j定義為兩邊界偏移1
        int x=arr[(l+r)/2];//取x為數(shù)組中間位置數(shù)
        while(i<j){
            do i++;while(arr[i]<x);
            do j--;while(arr[j]>x);
            //此時(shí)i指向的數(shù)字大于中軸數(shù)字, j指向數(shù)字小于中軸數(shù)字 交換
            if(i<j){
                int temp=arr[i];
                arr[i]=arr[j];
                arr[j]=temp;
            }
        }
        quickSort(arr,l,j);//退出循環(huán)是i==j 遞歸排序
        quickSort(arr,j+1,r);
    }

7.4 時(shí)間復(fù)雜度,空間復(fù)雜度以及穩(wěn)定性

  • 時(shí)間復(fù)雜度最好:O(nlog2n);
  • 時(shí)間復(fù)雜度最壞:O(n^2);
  • 時(shí)間復(fù)雜度平均:O(nlog2n);
  • 空間復(fù)雜度:O(nlog2n);
  • 穩(wěn)定性:不穩(wěn)定;

8.歸并排序

8.1 算法思想

將一個(gè)大的無(wú)序數(shù)組有序,我們可以把大的數(shù)組分成兩個(gè),然后對(duì)這兩個(gè)數(shù)組分別進(jìn)行排序,之后在把這兩個(gè)數(shù)組合并成一個(gè)有序的數(shù)組。由于兩個(gè)小的數(shù)組都是有序的,所以在合并的時(shí)候是很快的。

通過(guò)遞歸的方式將大的數(shù)組一直分割,直到數(shù)組的大小為 1,此時(shí)只有一個(gè)元素,那么該數(shù)組就是有序的了,之后再把兩個(gè)數(shù)組大小為1的合并成一個(gè)大小為2的,再把兩個(gè)大小為2的合并成4的 …… 直到全部小的數(shù)組合并起來(lái)。

8.2 動(dòng)畫(huà)演示

img

8.3 代碼示例

public static void mergerSort(int[]arr){
        mergerSortInternal(arr,0,arr.length-1);
    }
public static void mergerSortInternal(int[]arr,int l,int r) {//
        if (l >= r) return;
        int mid = (l + r) / 2;//把數(shù)組分為兩個(gè)
        mergerSortInternal(arr, l, mid);//對(duì)左邊數(shù)組遞歸排序
        mergerSortInternal(arr, mid + 1, r);//對(duì)右邊數(shù)組遞歸排序
        merge(arr,l,mid,r);//排序完成,進(jìn)行合并
    }
 public static void merge(int[]arr,int low,int mid,int high){
        int s1=low;//mid左側(cè)數(shù)組的頭和尾
        int e1=mid;
        int s2=mid+1;//mid右側(cè)數(shù)組的頭和尾
        int e2=high;
        int[]temp=new int[high-low+1];//定義一個(gè)數(shù)字,用來(lái)合并他們
        int k=0;//指示數(shù)組下標(biāo)
        while(s1<=e1&&s2<=e2){//選出兩側(cè)數(shù)組最小元素 插入temp數(shù)組
            if(arr[s1]<=arr[s2]) temp[k++]=arr[s1++];
            else temp[k++]=arr[s2++];
        }
        while(s1<=e1) temp[k++]=arr[s1++];//如果一側(cè)數(shù)組插入完畢,另一側(cè)還有剩余,則全部插入
        while(s2<=e2) temp[k++]=arr[s2++];
        for(int i=0;i<temp.length;i++){//返還到arr數(shù)組
            arr[i+low]=temp[i];
        }
    }
}

8.4 時(shí)間復(fù)雜度,空間復(fù)雜度以及穩(wěn)定性

  • 時(shí)間復(fù)雜度最好:O(nlog2n);
  • 時(shí)間復(fù)雜度最壞:O(nlog2n);
  • 時(shí)間復(fù)雜度平均:O(nlog2n);
  • 空間復(fù)雜度:O(n);

到此這篇關(guān)于Java數(shù)據(jù)結(jié)構(gòu)之基于比較的排序算法基本原理及具體實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Java 排序算法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring Hystrix熔斷報(bào)警原理圖例解析

    Spring Hystrix熔斷報(bào)警原理圖例解析

    這篇文章主要介紹了Spring Hystrix熔斷報(bào)警原理圖例解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-03-03
  • EL表達(dá)式簡(jiǎn)介_(kāi)動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    EL表達(dá)式簡(jiǎn)介_(kāi)動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    EL全名為Expression Language,這篇文章主要給大家介紹EL表達(dá)式的主要作用及內(nèi)容簡(jiǎn)介,感興趣的朋友一起看看
    2017-07-07
  • Java項(xiàng)目防止SQL注入的幾種方式

    Java項(xiàng)目防止SQL注入的幾種方式

    SQL注入是一種常見(jiàn)的攻擊方式,黑客試圖通過(guò)操縱應(yīng)用程序的輸入來(lái)執(zhí)行惡意SQL查詢(xún),從而繞過(guò)認(rèn)證和授權(quán),竊取、篡改或破壞數(shù)據(jù)庫(kù)中的數(shù)據(jù),本文主要介紹了Java項(xiàng)目防止SQL注入的幾種方式,感興趣的可以了解一下
    2023-12-12
  • Java object wait notify notifyAll代碼解析

    Java object wait notify notifyAll代碼解析

    這篇文章主要介紹了Java object wait notify notifyAll代碼解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-11-11
  • Maven-POM文件及組成部分

    Maven-POM文件及組成部分

    POM是用于描述Maven項(xiàng)目的配置文件,它包含了項(xiàng)目構(gòu)建、依賴(lài)管理和其他相關(guān)配置的信息,這篇文章主要介紹了Maven-POM文件,需要的朋友可以參考下
    2023-06-06
  • mybatis攔截器實(shí)現(xiàn)數(shù)據(jù)權(quán)限項(xiàng)目實(shí)踐

    mybatis攔截器實(shí)現(xiàn)數(shù)據(jù)權(quán)限項(xiàng)目實(shí)踐

    本文主要介紹了mybatis攔截器實(shí)現(xiàn)數(shù)據(jù)權(quán)限項(xiàng)目實(shí)踐,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • sprng和struts有什么區(qū)別?

    sprng和struts有什么區(qū)別?

    Spring和Struts都是近年來(lái)比較流行的框架,Struts主要用于表示層,Spring用于業(yè)務(wù)層,以及Hiberate主要用于持久層,
    2015-06-06
  • 如何把spring boot應(yīng)用發(fā)布到Harbor

    如何把spring boot應(yīng)用發(fā)布到Harbor

    這篇文章主要介紹了如何把spring boot應(yīng)用發(fā)布到Harbor,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11
  • Java中的BlockingQueue阻塞隊(duì)列原理以及實(shí)現(xiàn)詳解

    Java中的BlockingQueue阻塞隊(duì)列原理以及實(shí)現(xiàn)詳解

    這篇文章主要介紹了Java中的BlockingQueue阻塞隊(duì)列原理以及實(shí)現(xiàn)詳解,在最常見(jiàn)的使用到這個(gè)阻塞隊(duì)列的地方,就是我們耳熟能詳?shù)木€(xiàn)程池里面了,作為我們線(xiàn)程池的一大最大參與者,也是AQS的一個(gè)具體實(shí)現(xiàn),需要的朋友可以參考下
    2023-12-12
  • maven項(xiàng)目中<scope>provided</scope>的作用及說(shuō)明

    maven項(xiàng)目中<scope>provided</scope>的作用及說(shuō)明

    這篇文章主要介紹了maven項(xiàng)目中<scope>provided</scope>的作用及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-12-12

最新評(píng)論