快速排序

本身對快速排序的一些理解和心得算法

像是冒泡排序的升級版,也有着插入排序的影子,大多數狀況下,效率最高數組

核心思想:分而治之,與二分查找法有點聯繫,像是一種東西的正反兩用。測試

舉個生活中的例子,就像切豆腐,一塊豆腐切成兩塊,給兩我的,原先一我的的工做量,至關於兩我的完成,效率近似於一半(畢竟切開這個動做,再給兩我的這都是浪費效率的),而後兩塊豆腐再切開,最開始一我的的工做量,四我的共同完成,這就是快速排序爲何快。就像細胞分裂同樣,這種速度是至關恐怖的,也能夠想象下2的次冪
固然若是隻是很小的一塊豆腐,那這樣來回分,反倒不如直接一我的切來的快,因此,快速排序的時間複雜度(效率)會隨着數據量的增長,慢慢顯露出其明顯的優點,平均效率爲O(nlogn)
而咱們也能夠看出,豆腐切開的點,也就是入刀點尤爲重要,由於只有最中間的時候,纔是最快的,若是從豆腐的最邊緣切開,那無疑一我的,仍是切那一塊豆腐,而另外一我的徹底是摸魚了ui

選擇入刀點的方法:前人總結出來的比較優秀的一種方法,是開頭,結尾,中間位置取三個數,而後求中位數this

執行流程:quick方法,把第一次的實參傳遞給quickSort,並調用quickSort方法,quickSort,先調用median方法,取得中位數,而後依次執行完,再根據條件,是否繼續遞歸,所有遞歸完,順序就排好了spa

下面附上用js實現的代碼:prototype

<script>
    // 封裝一個方法,使原型方法之間能互相調用,更方便
    function Arr() {
        this.array = []

        //往數組裏添加元素
        Arr.prototype.insert = function (item) {
            this.array.push(item)
        }
        
        //把結果轉換爲字符串形式
        Arr.prototype.toString = function () {
            return this.array.join()
        }
    
        //兩個數進行交換
        Arr.prototype.swap = function (m, n) {
            var temp = this.array[m]
            this.array[m] = this.array[n]
            this.array[n] = temp
        }

        // 選擇入刀點
        Arr.prototype.median = function (left, right) {
            // 1.求出中間的位置,這裏必須用向下取整,否則會形成無限遞歸
            var center = Math.floor((left + right) / 2)

            // 2.經過交換,把中位數放到中間的位置
            if (this.array[left] > this.array[center]) {
                this.swap(left, center)
            }
            if (this.array[center] > this.array[right]) {
                this.swap(center, right)
            }
            if (this.array[left] > this.array[center]) {
                this.swap(left, center)
            }

            // 3. 將center移動到right - 1的位置,這個時候能得出center必定比right位置的數小
//再以後就是left和center之間的數依次和center比大小,而後最後把center放到一個正好的位置
//左面的數所有比它小,右面的所有比它大 this.swap(center, right - 1) // 4.返回入刀點 return this.array[right - 1] } // 快速排序實現 Arr.prototype.quick = function () { //第一次調用quickSort,並把實參傳過去,以後就是quickSort遞歸了 this.quickSort(0, this.array.length - 1) } Arr.prototype.quickSort = function (left, right) { // 0.遞歸結束條件 if (left >= right) return // 1.獲取樞紐 var pivot = this.median(left, right) // 2.開始進行交換 var i = left var j = right - 1 while (true) { //表明一個死循環 while (this.array[++i] < pivot) { } while (this.array[--j] > pivot) { } if (i < j) { this.swap(i, j) } else { break //不知足if條件,此時中斷死循環 } } // 3.將樞紐放在正確的位置,由於前面已經排好,因此有限制條件,否則會形成重複排序 if(i<right-1){ this.swap(i, right - 1)} // 4.遞歸調用左邊部分 this.quickSort(left, i - 1) // 4.遞歸調用右邊部分 this.quickSort(i + 1, right) } } // 初始化數據項 var list = new Arr() list.insert(7) list.insert(11) list.insert(70) list.insert(10) list.insert(6) list.insert(5) list.insert(101) list.insert(99) list.insert(50) list.insert(100) alert(list) // 7,11,70,10,6,5,101,99,50,100 list.quick()// 測試快速排序 alert(list)//5,6,7,10,11,50,70,99,100,101 </script>

多畫畫圖比較容易理清code

關鍵詞:分而治之,遞歸,中位數,冒泡排序升級版blog

注意:快速排序不是一種穩定的算法,何爲穩定,簡單來講就是兩個大小同樣的數,屢次用同一排序算法,兩個數字出現的位置是否同樣
快速排序有多種寫法,可是核心思想都是分而治之排序

相關文章
相關標籤/搜索