關於八大排序演算法(C )

2021-10-07 15:25:30 字數 4336 閱讀 7795

本文針對leetcode912:排序陣列作乙個排序的總結:題目鏈結

本題最快使用桶排序,歸併排序也可以很快通過,所以這兩個排序方法強烈推薦。

——————修改版本2020/7/5 :新增一些易錯點和原理解釋。——————修改版本2020/8/16:新增關於穩定性分類和複雜度歸類對比。

交換/插入類排序:常常比較冒泡和快排之間的差別

歸併排序:又穩定又快

計數排序/桶排序:很神!超快!

演算法按照穩定性為分類,共分為兩類:

附加說明:理解選擇排序的穩定性

時間複雜度:o(n^2)

空間複雜度:o(1)

vector<

int>

selectsort

(vector<

int>

& nums)}if

(mini_num!=i)

}return nums;

}

原理:

#1.先改造成大頂堆,從最後乙個子樹開始調整。最後一棵子樹的父節點為:i=nums.size()/2-1 (i從0開始)。

#2.調整好之後,把最頂端的節點與最後節點調換,此時最大值確定。

#3.確定最大值之後,需要將除最後節點的剩下樹繼續調整為大頂堆,以後以此類推。

時間複雜度:o(n*log(n)),穩定

空間複雜度:o(1)

vector<

int>

heapsort

(vector<

int>

& nums)

//將最頂端的最大值nums[0]與最後葉子nums[n-1]交換,再對最頂端進行調整

for(

int i=nums.

size()

-1;i>

0;i--

)return nums;

}vector<

int>

adjust

(vector<

int>

& nums,

int n,

int size)

if(rightchild

>nums[largest])if

(largest!=n)

return nums;

}

時間複雜度: o(n^2)

如果有flag標誌可以是o(1),適用於當一開始序列就已經依次排好的情況。

空間複雜度: o(1)

vector<

int>

bubblesort

(vector<

int>

& nums)}if

(flag==0)

}return nums;

}

時間複雜度:最優為o(n*log(n)),最差為o(n^2),不穩定

空間複雜度:o(1)

演算法原理與比較:

快速排序,選出乙個樞紐元素,將這個樞紐元素和陣列所有元素進行比較,把彼樞紐元素大的元素放在樞紐元素右邊,把比樞紐元素小的放在樞紐元素左邊,

而對於一趟快速排序要比較n次,每一趟快排的時間複雜度是o(n)

接下來你要對快排劃分出來的兩個子陣列進行遞迴快排,如果每一趟快排很平均的將陣列劃分為兩個子陣列,那麼遞迴快排的深度就是o(logn),所以總的時間複雜度就是o(nlogn)。

但是快排可以退化成冒泡,一旦每一趟快排,不幸的選擇出最大或最小元素作為樞紐元素,那麼遞迴深度將變成n,則時間複雜度變成了o(n^2),此時快排的效率降到最低,退化為冒泡。

所以快排對於樞紐元素的選擇上很關鍵,如果能選擇出每趟平均劃分陣列的樞紐元素,那麼快排的效率最高,如何選擇樞紐元素將成為衡量快排的關鍵,可以使用三者取中法來選擇,每趟快排前,先將陣列開始位置,中間位置,以及結尾位置的三個元素進行比較,選擇其中的中間大的數做為樞紐元素,這樣可以降低退化成冒泡的風險

**中選擇較簡單的方法:隨機取陣列中的乙個數做為樞紐元素,這樣也可以降低風險。

c++**:

vector<

int>

quicksort

(int left,

int right,vector<

int>

& nums)

int low=left;

int high=right;

//隨機取key值,降低風險

swap

(nums[

rand()

%right+1]

,nums[left]);

int key=nums[left]

;while

(left

for(

;left

)swap

(nums[left]

,nums[right]);

}quicksort

(low,left,nums)

;quicksort

(left+

1,high,nums)

;return nums;

}

時間複雜度:o(n^2)

空間複雜度:o(1)

vector<

int>

insertsort

(vector<

int>

& nums)}}

return nums;

}

時間複雜度:未解問題

空間複雜度:o(1)

vector<

int>

shellsort

(vector<

int>

& nums)}}

return nums;

}

分治+合併,演算法示意圖:

空間複雜度:o(n)

vector<

int>

mergesort

(int left,

int right, vector<

int>

& nums);}

if(left==right);}

int mid=

(left+right)/2

;//易錯點1:mid的地方應該基於left

//分治

auto ln=

mergesort

(left,mid,nums)

;auto rn=

mergesort

(mid+

1,right,nums)

; vector<

int> res;

int i=

0,j=0;

while

(isize()

&&jsize()

)else

}while

(isize()

)while

(jsize()

)return res;

}

舉例:現在給了待排序的陣列[5, 3, 5, 2, 8]。那麼:

#1.申請(8-2+1)共7個桶用於放元素,桶為:0~6號桶 ( 後面得到的旗子位置記得加上low:2)。

#2.遍歷待排序的陣列[5, 3, 5, 2, 8],把對應的桶裡面放入小旗子,即 2-2=0、3-2=1、8-2=6 號桶各放了乙個旗子, 5-2=3號 桶裡放了兩個旗子。

#3.從 0 到 6 遍歷一遍所有的桶,如果桶裡沒有小旗子就跳過,有小旗子就往結果裡放入小旗子個數的該元素,加上最小值2,得到[2, 3, 5, 5, 8]。

時間複雜度:o(n)

空間複雜度:o(n)

特點:時間複雜度低,但是空間複雜度高。而且在排序前需要提前知道一些資訊,比如排序的大致範圍。

八大排序演算法

1.直接插入排序 原理 將陣列分為無序區和有序區兩個區,然後不斷將無序區的第乙個元素按大小順序插入到有序區中去,最終將所有無序區元素都移動到有序區完成排序。要點 設立哨兵,作為臨時儲存和判斷陣列邊界之用。實現 void insertsort node l,int length void shell ...

八大排序演算法

一 概述 八大排序演算法包括 1 插入排序之直接插入排序 straight insertion sort 2 插入排序之希爾排序 shells sort 3 選擇排序之簡單選擇排序 selection sort 4 選擇排序之堆排序 heap sort 5 交換排序之氣泡排序 bubble sort...

八大排序演算法

排序的定義 輸入 n個數 a1,a2,a3,an 輸出 n個數的排列 a1 a2 a3 an 使得a1 a2 a3 an in place sort 不占用額外記憶體或占用常數的記憶體 插入排序 選擇排序 氣泡排序 堆排序 快速排序。out place sort 歸併排序 計數排序 基數排序 桶排序...