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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

算法小白——基本排序算法入门

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

計算的 時間復雜度(最差、平均、和最好性能),依據列表(list)的大小(n)。一般而言,好的性能是O(n log n),且壞的性能是O(n^2)。對于一個排序理想的性能是O(n)。僅使用一個抽象關鍵比較運算的排序算法總平均上總是至少需要O(n log n)。

插入排序(insertion sort)

插入排序應該算是最簡單和容易理解的排序算法。它的工作原理是通過構建有序序列,對于未排序數據,在已排序序列中從后向前掃描,找到相應位置并插入。具有n個元素時它需要經過n-1趟排序。對于p = 1到p = n-1趟,插入排序保證從位置0到位置p上的元素為已排序狀態。它就是基于這個事實來排序的。

function sort(arr) {if(arr.length <= 1) {return arr}for(var i=0; i<arr.length; i++) {for(var j=i-1; j>=0; j--) {if(arr[j+1] < arr[j]) {var temp = arr[j+1];arr[j+1] = arr[j];arr[j] = temp}}}return arr }

如果目標是把n個元素的序列升序排列,那么采用插入排序存在最好情況和最壞情況。最好情況就是,序列已經是升序排列了,在這種情況下,需要進行的比較操作需(n-1)次即可。最壞情況就是,序列是降序排列,那么此時需要進行的比較共有n(n-1)/2次。插入排序的賦值操作是比較操作的次數減去(n-1)次。平均來說插入排序算法復雜度為O(n^2)。因而,插入排序不適合對于數據量比較大的排序應用。但是,如果需要排序的數據量很小,例如,量級小于千,那么插入排序還是一個不錯的選擇。 插入排序在工業級庫中也有著廣泛的應用,在STL的sort算法和stdlib的qsort算法中,都將插入排序作為快速排序的補充,用于少量元素的排序(通常為8個或以下)

冒泡排序(bubble sort)

冒泡排序是與插入排序擁有相等的運行時間,但是兩種算法在需要的交換次數卻很大地不同。在最好的情況,冒泡排序需要O(n^2)次交換,而插入排序只要最多O(n)交換。冒泡排序的實現(類似下面)通常會對已經排序好的數列拙劣地運行O(n^2),而插入排序在這個例子只需要O(n)個運算。因此很多現代的算法教科書避免使用冒泡排序,而用插入排序替換之。冒泡排序如果能在內部循環第一次運行時,使用一個旗標來表示有無需要交換的可能,也可以把最好的復雜度降低到O(n)。在這個情況,已經排序好的數列就無交換的需要。若在每次走訪數列時,把走訪順序反過來,也可以稍微地改進效率。有時候稱為雞尾酒排序,因為算法會從數列的一端到另一端之間穿梭往返。

冒泡排序算法的運作如下:

  • 比較相鄰的元素。如果第一個比第二個大,就交換他們兩個。

  • 對每一對相鄰元素作同樣的工作,從開始第一對到結尾的最后一對。這步做完后,最后的元素會是最大的數。

  • 針對所有的元素重復以上的步驟,除了最后一個。

  • 持續每次對越來越少的元素重復上面的步驟,直到沒有任何一對數字需要比較。

由于它的簡潔,冒泡排序通常被用來對于程序設計入門的學生介紹算法的概念。

function bubbleSort(arr) {if(arr.length <= 1) {return arr;}for(var j=0; j<arr.length; j++) {for(var i=0; i<arr.length-j; i++) {if(arr[i] > arr[i+1]) {var tmp = arr[i];arr[i] = arr[i+1];arr[i+1] = tmp;}}}return arr; }

選擇排序(selection sort)

選擇排序(Selection sort)是一種簡單直觀的排序算法。它的工作原理如下。首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再從剩余未排序元素中繼續尋找最小(大)元素,然后放到已排序序列的末尾。以此類推,直到所有元素均排序完畢。
選擇排序的主要優點與數據移動有關。如果某個元素位于正確的最終位置上,則它不會被移動。選擇排序每次交換一對元素,它們當中至少有一個將被移到其最終位置上,因此對n個元素的表進行排序總共進行至多n-1次交換。在所有的完全依靠交換去移動元素的排序方法中,選擇排序屬于非常好的一種。

復雜度分析

選擇排序的交換操作介于 0 和(n-1)次之間。選擇排序的比較操作為n(n-1)/2次之間。選擇排序的賦值操作介于0和3(n-1)次之間。比較次數O(n^2),比較次數與關鍵字的初始狀態無關,總的比較次數 N=(n-1)+(n-2)+...+1=n(n-1)/2。交換次數O(n),最好情況是,已經有序,交換0次;最壞情況是,逆序,交換n-1次。交換次數比冒泡排序較少,由于交換所需CPU時間比比較所需的CPU時間多, n值較小時,選擇排序比冒泡排序快。
原地操作幾乎是選擇排序的唯一優點,當空間復雜度要求較高時,可以考慮選擇排序;實際適用的場合非常罕見。

function selectionSort(arr) {if(arr.length <= 1) {return arr}var i, j, min;var temp;for (i = 0; i < arr.length - 1; i++) {min = i;for (j = i + 1; j < arr.length; j++) {if (arr[min] > arr[j])min = j;temp = arr[min];arr[min] = arr[i];arr[i] = temp;}}return arr }

快速排序(quick sort)

快速排序使用分治法(Divide and conquer)策略來把一個序列(list)分為兩個子序列(sub-lists)。

步驟為:

  • 從數列中挑出一個元素,稱為"基準"(pivot),

  • 重新排序數列,所有元素比基準值小的擺放在基準前面,所有元素比基準值大的擺在基準的后面(相同的數可以到任一邊)。在這個分區結束之后,該基準就處于數列的中間位置。這個稱為分區(partition)操作。

  • 遞歸地(recursive)把小于基準值元素的子數列和大于基準值元素的子數列排序。
    遞歸的最底部情形,是數列的大小是零或一,也就是永遠都已經被排序好了。雖然一直遞歸下去,但是這個算法總會結束,因為在每次的迭代(iteration)中,它至少會把一個元素擺到它最后的位置去。

  • 正如它的名字,快速排序是在時間中最快的已知排序算法,它的平均運行時間是O(NlogN)。快速排序也是一種分治的遞歸算法。將數組S排序的基本算法由下列簡單的四步組成:

  • 如果S中元素個數是0或1,則返回

  • 取S中任一元素v,稱之為樞紐元

  • 將S - {v}分成兩個不相交的集合:S1 = {x∈S - {v} | x ≤ v}和S2 = {x∈S - {v} | x ≥ v}

  • 返回{quicksort(S1)},繼續v,繼而quicksort(S2)
    由于對樞紐元的處理會導致第三步中的分割不唯一,因此,我們希望把等于樞紐元的大約一半的關鍵字分到S1中,而另外一半分到S2中,那怎么去選擇一個好的樞紐元呢?

  • 選取樞紐元
    一種錯誤的方法
    通常的,沒有經過充分考慮的選擇是將第一個元素用作樞紐元。如果輸入是隨機的,那么這是可以接受的,但是如果輸入是預排序或是反序的,那么這樣的樞紐元就會產生一個劣質的分割,因為所有的元素不是都被劃入S1就是被劃入S2。
    一種安全的作法
    一種安全的方針是隨機選取樞紐元。但是另一方面,隨機數的生成一般是昂貴的,根本減少不了算法奇遇部分的平均運行時間。
    三數中值分割法
    一組N個數的中值是第Math.ceil(N/2)個最大的數。樞紐元的最好的選擇是數組的中值。不幸的是,這很難算出,且會減慢快速排序的速度。因此一般的做法是使用左端、右端和中心位置上的三個元素的中值作為樞紐元。例如,輸入為8, 1, 4, 9, 6, 3, 5, 2, 7, 0,它的左邊元素是8,右邊元素是0,中心位置為Math.floor((left + right) / 2)上的元素是6,于是樞紐元v=6。

    function quickSort(arr) {if (arr.length <= 1) {return arr.slice(0);}var left = [];var right = [];var mid = [arr[0]]; //first number as a pivotfor (var i = 1; i < arr.length; i++) {if (arr[i] < mid[0]) {left.push(arr[i]);} else {right.push(arr[i]);}}return quickSort(left).concat(mid.concat(quickSort(right))); }

    總結

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

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