日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

基本排序算法一

發布時間:2023/12/4 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 基本排序算法一 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一 選擇排序

原理:選擇排序很簡單,他的步驟如下:

  • 從左至右遍歷,找到最小(大)的元素,然后與第一個元素交換。
  • 從剩余未排序元素中繼續尋找最小(大)元素,然后與第二個元素進行交換。
  • 以此類推,直到所有元素均排序完畢。
  •  之所以稱之為選擇排序,是因為每一次遍歷未排序的序列我們總是從中選擇出最小的元素。下面是選擇排序的動畫演示:

    ?

    public class Sort {//選擇排序public static void SelectionSort(int[] array) {int n = array.length;for (int i = 0; i < n; i++) {int min = i; // 從第i+1個元素開始,找最小值for (int j = i + 1; j < n; j++) {if (array[min] > array[j])min = j;}Swap(array, i, min);}}//插入排序public static void insertionSort(int[] array){int n = array.length;for (int i =1; i < n; i++) {for (int j = i; j >0; j--) {if (array[j] < array[j-1])Swap(array, j, j-1);elsebreak;} }}//冒泡排序public static void bubbleSort(int[] array){int n = array.length;for (int i =0; i < n; i++) {for (int j = n-1; j >i; j--) {if (array[j] < array[j-1])Swap(array, j, j-1);} }}//希爾排序public static void shellSort(int[] arr){int N=arr.length;int h=1;while(h<N/3){h=3*h+1;}while (h>=1) {for(int i =h; i <N; i++) {for (int j =i; j>=h&&(arr[j]<arr[j-h]); j-=h) {swap(arr, j, j-h); }}h=h/3;}}private static void Swap(int[] array, int i, int min) {int temp = array[i];array[i] = array[min];array[min] = temp;}private static void printArr(int[] array){for (int i = 0; i < array.length; i++) {System.out.print(array[i]+" ");}System.out.println("");}public static void main(String[] args) {int[] array = new int[] { 1, 3, 1, 4, 2, 4, 2, 3, 2, 4, 7, 6, 6, 7, 5,5, 7, 7 };System.out.println("Before Sort:");printArr(array);//SelectionSort(array);//insertionSort(array); bubbleSort(array);System.out.println("After Sort:");printArr(array);} } View Code

      下圖分析了選擇排序中每一次排序的過程,您可以對照圖中右邊的柱狀圖來看。

    (array);

      分析:

      選擇排序的在各種初始條件下的排序效果如下:

  • 選擇排序需要花費 (N – 1) + (N – 2) + … + 1 + 0 =?N(N- 1) / 2 ~ N2/2次比較 和?N-1次交換操作。
  • 對初始數據不敏感,不管初始的數據有沒有排好序,都需要經歷N2/2次比較,這對于一些原本排好序,或者近似排好序的序列來說并不具有優勢。在最好的情況下,即所有的排好序,需要0次交換,最差的情況,倒序,需要N-1次交換。
  • 數據交換的次數較少,如果某個元素位于正確的最終位置上,則它不會被移動。在最差情況下也只需要進行N-1次數據交換,在所有的完全依靠交換去移動元素的排序方法中,選擇排序屬于比較好的一種。
  • 二 插入排序

    原理

      插入排序也是一種比較直觀的排序方式。可以以我們平常打撲克牌為例來說明,假設我們那在手上的牌都是排好序的,那么插入排序可以理解為我們每一次將摸到的牌,和手中的牌從左到右依次進行對比,如果找到合適的位置則直接插入。具體的步驟為:

  • 從第一個元素開始,該元素可以認為已經被排序
  • 取出下一個元素,在已經排序的元素序列中從后向前掃描
  • 如果該元素小于前面的元素,則依次與前面元素進行比較如果小于則交換,直到找到大于該元素的就則停止;
  • 如果該元素大于前面的元素(已排序),則重復步驟2
  • 重復步驟2~4 直到所有元素都排好序 。
  •   下面是插入排序的動畫演示:

    分析:

      插入排序的在各種初始條件下的排序效果如下:

      1. 插入排序平均需要N2/4次比較和N2/4 次交換。在最壞的情況下需要N2/2 次比較和交換;在最好的情況下只需要N-1次比較和0次交換。

      先考慮最壞情況,那就是所有的元素逆序排列,那么第i個元素需要與前面的i-1個元素進行i-1次比較和交換,所有的加起來大概等于N(N- 1) / 2 ~ N2?/ 2,在數組隨機排列的情況下,只需要和前面一半的元素進行比較和交換,所以平均需要N2/4次比較和N2/4 次交換。

      在最好的情況下,所有元素都排好序,只需要從第二個元素開始都和前面的元素比較一次即可,不需要交換,所以為N-1次比較和0次交換。

      2. 插入排序中,元素交換的次數等于序列中逆序元素的對數。元素比較的次數最少為元素逆序元素的對數,最多為元素逆序的對數 加上數組的個數減1。

      3.總體來說,插入排序對于部分有序序列以及元素個數比較小的序列是一種比較有效的方式。

      如上圖中,序列AEELMOTRXPS,中逆序的對數為T-R,T-P,T-S,R-P,X-S 6對。典型的部分有序隊列的特征有:

    • 數組中每個元素離最終排好序后的位置不太遠
    • 小的未排序的數組添加到大的已排好序的數組后面
    • 數組中只有個別元素未排好序

      對于部分有序數組,插入排序是比較有效的。當數組中逆元素的對數越低,插入排序要比其他排序方法要高效的多。

      選擇排序和插入排序的比較

      上圖展示了插入排序和選擇排序的動畫效果。圖中灰色的柱子是不用動的,黑色的是需要參與到比較中的,紅色的是參與交換的。圖中可以看出:插入排序不會動右邊的元素,選擇排序不會動左邊的元素;由于插入排序涉及到的未觸及的元素要比插入的元素要少,涉及到的比較操作平均要比選擇排序少一半。

    3.冒泡排序

      冒泡排序也被稱為下沉排序,是一個簡單的排序算法,通過多次重復比較每對相鄰的元素,并按規定的順序交換他們,最終把數列進行排好序。一直重復下去,直到結束。該算法得名于較小元素“氣泡”會“浮到”列表頂部。由于只使用了比較操作,所以這是一個比較排序。冒泡排序算法的運作如下:

  • 比較相鄰的元素。如果第一個比第二個大,就交換他們兩個。
  • 對每一對相鄰元素作同樣的工作,從開始第一對到結尾的最后一對。這步做完后,最后的元素會是最大的數。
  • 針對所有的元素重復以上的步驟,除了最后一個。
  • 持續每次對越來越少的元素重復上面的步驟,直到沒有任何一對數字需要比較。
  •   時間復雜度

      若文件的初始狀態是正序的,一趟掃描即可完成排序。所需的關鍵字比較次數 C和記錄移動次數 M均達到最小值: Cmin=n-1,Mmin=0。所以,冒泡排序最好的時間復雜度為 O(n)。 ?      若初始文件是反序的,需要進行 n-1趟排序。每趟排序要進行 n-i次關鍵字的比較(1≤i≤n-1),且每次比較都必須移動記錄三次來達到交換記錄位置。在這種情況下,比較和移動次數均達到最大值:   冒泡排序的最壞時間復雜度為O(n*n)綜上,因此冒泡排序總的平均時間復雜度為O(n*n)。

      算法穩定性

      冒泡排序就是把小的元素往前調或者把大的元素往后調。比較是相鄰的兩個元素比較,交換也發生在這兩個元素之間。所以,如果兩個元素相等,我想你是不會再無聊地把他們倆交換一下的;如果兩個相等的元素沒有相鄰,那么即使通過前面的兩兩交換把兩個相鄰起來,這時候也不會交換,所以相同元素的前后順序并沒有改變,所以冒泡排序是一種穩定排序算法。

      ?

    希爾排序

      原理:希爾排序也稱之為遞減增量排序,它是對插入排序的改進。在插入排序中,我們知道,插入排序對于近似已排好序的序列來說,效率很高,可以達到線性排序的效率。但是插入排序效率也是比較低的,他 一次只能將數據向前移一位。比如如果一個長度為N的序列,最小的元素如果恰巧在末尾,那么使用插入排序仍需一步一步的向前移動和比較,要N-1次比較和交 換。希爾排序通過將待比較的元素劃分為幾個區域來提升插入排序的效率。這樣可以讓元素可以一次性的朝最終位置邁進一大步,然后算法再取越來越小的步長進行排序,最后一步就是步長為1的普通的插入排序的,但是這個時候,整個序列已經是近似排好序的,所以效率高。

      如下圖,我們對下面數組進行 排序的時候,首先以4為步長,這是元素分為了LMPT,EHSS,ELOX,AELR幾個序列,我們對這幾個獨立的序列 進行插入排序,排序完成之后,我們減小步長繼續排序,最后直到步長為1,步長為1即為一般的插入排序,他保證了元素一定會被排序。

      希爾排序的增量遞減算法可以隨意指定,可以以N/2遞減,只要保證最后的步長為1即可。

    實現:

    public static void shellSort(int[] arr){int N=arr.length;int h=1;while(h<N/3){h=3*h+1;}while (h>=1) {for(int i =h; i <N; i++) {for (int j =i; j>=h; j-=h) {if(arr[j]<arr[j-h]){swap(arr, j, j-h);}else{break;}}}h=h/3;} }

      可以看到,希爾排序的實現是在插入排序的基礎上改進的,插入排序的步長為1,每一次遞減1,希爾排序的步長為我們定義的h,然后每一次和前面的-h位置上的元素進行比較。算法中,我們首先獲取小于N/3 的最大的步長,然后逐步長遞減至步長為1的一般的插入排序。

      下面是希爾排序在各種情況下的排序動畫:

    分析:

    1. 希爾排序的關鍵在于步長遞減序列的確定,任何遞減至1步長的序列都可以,目前已知的比較好的序列有:

    • Shell’s 序列: N/2 , N/4 , …, 1 (重復除以2);
    • Hibbard’s 序列: 1, 3, 7, …, 2k?– 1 ;
    • Knuth’s 序列: 1, 4, 13, …, (3k?– 1) / 2 ;該序列是本文代碼中使用的序列。
    • 已知最好的序列是 Sedgewick’s (Knuth的學生,Algorithems的作者)的序列: 1, 5, 19, 41, 109, ….

    該序列由下面兩個表達式交互獲得:

    • 1, 19, 109, 505, 2161,….., 9(4k?– 2k) + 1, k = 0, 1, 2, 3,…
    • 5, 41, 209, 929, 3905,…..2k+2?(2k+2?– 3 ) + 1, k = 0, 1, 2, 3, …

      “比較在希爾排序中是最主要的操作,而不是交換。”用這樣步長的希爾排序比插入排序和堆排序都要快,甚至在小數組中比快速排序還快,但是在涉及大量數據時希爾排序還是比快速排序慢。

      2. 希爾排序的分析比較復雜,使用Hibbard’s 遞減步長序列的時間復雜度為O(N3/2),平均時間復雜度大約為O(N5/4) ,具體的復雜度目前仍存在爭議。

      3. 實驗表明,對于中型的序列( 萬),希爾排序的時間復雜度接近最快的排序算法的時間復雜度nlogn。

      最后總結一下本文介紹的三種排序算法的最好最壞和平均時間復雜度。

    名稱最好平均最壞內存占用穩定排序
    插入排序nn2n21
    選擇排序n2n2n21
    希爾排序nnlog2n

    n3/2
    依賴于增量遞減序列目前最好的是 nlog2n1

    轉載于:https://www.cnblogs.com/wxgblogs/p/5499569.html

    總結

    以上是生活随笔為你收集整理的基本排序算法一的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。