亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

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

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

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

1.1常見基于比較的排序分類

在這里插入圖片描述

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

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

2.直接插入排序

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

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

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

2.2 直接插入排序動畫演示

在這里插入圖片描述

2.3 代碼示例

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

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

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

3. 希爾排序

3.1 算法思想

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

3.2 圖片演示

3.3 代碼示例

public static void hell(int[] arr,int gap){//當gap=1時 其實就是直接插入排序
        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 時間復雜度,空間復雜度以及穩(wěn)定性

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

4.選擇排序

4.1 算法思想

選擇排序(Selection-sort)是一種簡單直觀的排序算法。它的工作原理:首先在未排序序列中找到最?。ù螅┰兀娣诺脚判蛐蛄械钠鹗嘉恢?,然后,再從剩余未排序元素中繼續(xù)尋找最?。ù螅┰?,然后放到已排序序列的末尾。以此類推,直到所有元素均排序完畢。

4.2 動畫演示

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 時間復雜度,空間復雜度以及穩(wěn)定性

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

5.堆排序

5.1 算法思想

堆是具有以下性質的完全二叉樹:每個結點的值都大于或等于其左右孩子結點的值,稱為大頂堆;或者每個結點的值都小于或等于其左右孩子結點的值,稱為小頂堆。如下圖:

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

img

5.2 動畫演示

img

5.3 代碼示例

public static void heapSort(int[] arr){//排序方法
        creatHeap(arr);
        int end=arr.length-1;
    //因為是大根堆,所以根節(jié)點值為最大值,根節(jié)點與最后一個節(jié)點值交換 輸出并刪除此時最后一個節(jié)點,然后向下調整根節(jié)點
        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){//向下調整操作
        int parent=root;
        int child=parent*2+1;
        while(child<len){
            if(child+1<len&&arr[child]<arr[child+1]){//待調整節(jié)點右子樹大于左子樹
                child++;
            }
            if(arr[child]>arr[parent]){//由于是大根堆,如果兒子節(jié)點值大于父親節(jié)點就交換
                int temp=arr[parent];
                arr[parent]=arr[child];
                arr[child]=temp;
                parent=child;//繼續(xù)向下調整,防止調整后不滿足大根堆的條件
                child=parent*2+1;
            }else break;
        }
    }

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

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

6.冒泡排序

6.1 算法思想

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

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

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

6.2 動畫演示

img

6.3 代碼示例

public static void bubbleSort(int[] arr){
        for(int i=0;i<arr.length-1;i++){//外層循環(huán)控制趟數(shù)
            boolean flag=false;//一個標記進行優(yōu)化
            for(int j=0;j<arr.length-1-i;j++){//內層循環(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)走完沒有交換,說明已經有序,直接break
        }
    }

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

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

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

7.1 算法思想

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

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

7.2 動畫演示

img

7.3 代碼示例

//該代碼參考acwing創(chuàng)始人yxc的快排模板
public static void quickSort(int[] arr,int l,int r){
        if(l>=r) return;//每次判斷傳進來左右下標
        int i=l-1,j=r+1;//因為在循環(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);
            //此時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 時間復雜度,空間復雜度以及穩(wěn)定性

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

8.歸并排序

8.1 算法思想

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

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

8.2 動畫演示

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

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

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

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

相關文章

  • Spring Hystrix熔斷報警原理圖例解析

    Spring Hystrix熔斷報警原理圖例解析

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

    EL表達式簡介_動力節(jié)點Java學院整理

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

    Java項目防止SQL注入的幾種方式

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

    Java object wait notify notifyAll代碼解析

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

    Maven-POM文件及組成部分

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

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

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

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

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

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

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

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

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

    maven項目中<scope>provided</scope>的作用及說明

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

最新評論