常見的排序演算法可以分為兩大類:
非線性時間比較類: 通過比較決定元素間的相對次序,最小時間複雜度為 o(nlogn)演算法複雜度線性時間非比較類:不通過比較決定元素間的相對次數,線性時間執行
比較相鄰元素的相對大小,如果反序則交換,如果是從小到大排序,那麼第一次掃瞄可以確定最大的元素,第二次掃瞄確定次大元素,以此類推,需要n-1次掃瞄。
**:
void
bubblesort
(std::vector<
int>
&v)}
}
每次從序列中找乙個base,然後遍歷陣列中剩下的元素,將比base小的元素放在base的左邊,比base大的元素放在base的右邊。
過程中通過乙個left以及right指標,分別找到左邊第乙個大於base的元素以及右邊第乙個小於base的元素,然後交換兩者,left++, right–,知道left=right。然後將left元素與base進行交換。
void
quicksort
(vector<
int>
& v,
int left,
int right)
swap
(v[l]
, v[left]);
quicksort
(v,0
, left-1)
;quicksort
(v, left+
1, r)
;}
基本思想如下:
對於a[n], 假定 a[0] - a[n-1]之間的元素是已經排序的,那麼只需遍歷a[0,n-1]找到第乙個大於a[n]的元素,將a[n]放在這個元素前面(實現過程中比較從j=n->1比較a[j]與a[j-1]的大小)。
**:i從1開始到size-1, j從i開始尋找合適位置插入
void
insertsort
(vector<
int>
&v) v[j]
= tmp;
}}
簡單的插入排序需要一步步對元素進行比較、移動、插入,尤其是極端倒序情況。希爾排序採用跳躍式分組的策略,通過增量gap對元素進行分組,然後對分組內的元素進行插入排序,然後逐步縮小增量直到gap=1。
希爾排序通過分組策略然後組內插入排序,使得陣列巨集觀基本有序,相比插入排序不會涉及過多的資料移動。
**:
void
shellsort
(vector<
int>
& v)
v[j]
= temp;}}
}
注意雖然希爾排序使用到插入排序實現,但是在組內進行插入排序的時候相同元素可能順序會調換,因此是不穩定的
選擇排序原理如下:初始狀態下整個陣列無序,從其中找到最小的元素放在陣列第乙個位置作為已排序。然後對剩下未排序元素繼續尋找最小元素放在已排序元素的末尾。
與氣泡排序相比:氣泡排序每次掃瞄都需要交換相鄰的逆序對,然後確定最大(最小)元素放到合適的位置。選擇排序每次掃瞄直接記錄最大(最小)元素的位置,然後只需要一次交換放到合適的位置。
void
selectsort
(vector<
int>
& v)
swap
(v[temp]
, v[i]);
}}
歸併排序採用分治思想,將問題分為一些小問題然後遞迴求解,而治的階段將小問題的答案結合在一起求解。
歸併排序必須引入新的空間來儲存原陣列兩部分有序子陣列的合併結果,然後在拷貝回原陣列之中。
void
merge
(vector<
int>
& v,
int left,
int mid,
int right)
else
}for
(int i=
0;ivoid
mergesort
(vector<
int>
&v,int left,
int right)
堆的本質是一顆完全二叉樹,兩個性質:
堆的每個父節點(大於 或者小於)子節點
堆的左右子樹同樣也是堆
由於是一顆完全二叉樹,可以按照層序遍歷順序編號,使用陣列表示堆, i節點的父節點的下標為(i-1)/2
, 左右孩子的下標為2*i + 1
與2*i+2
。
堆排序的步驟如下:
建堆(公升序建立最大堆), 建堆過程中從最後乙個非葉節點到根節點調整堆。調整堆:迴圈n-1次,每次將堆頂元素與未排序的最後乙個元素(從n-1到1)進行交換,然後從根元素向下調整。
void
adjust
(vector<
int>
& v,
int size,
int idx)
}
左右孩子計算下標:idx*2 + 1(2)
獲取非葉節點與左右孩子的最大值,如果不是該非葉節點需要進行交換,然後切記: 還需要對與之交換的那個節點進行調整
建立堆並實現排序:
首先從最後乙個非葉節點往根節點開始遍歷調整,建立堆。然後將堆頂元素與無序陣列的最後乙個元素進行交換,(一共需要交換size-1次,每次都能在原陣列末尾確定當前最大元素)每次交換完成之後需要重新從根節點開始調整,但是調整範圍只涉及size-1個元素。
void
heapsort
(vector<
int>
& v)
// n-1 swap
for(
int i=size-
1;i>=
1;i--
)}
基數排序與其他七種排序演算法不同,不需要進行關鍵字比較。
將所有的數值按照位數從低到高的順序計算當前位大小,然後放入對應的桶中,那麼對於當前位來說,所有桶中元素的順序即為當前位的大小順序,即當前位有序。通過不斷將位數增加,使得每一位有序,那麼最終結果有序
**:
// 統計陣列內的最大位數
intgetbits
(vector<
int> v)
bits =
max(bits, cnt);}
return bits;
}// 對每個位使用乙個桶(vector)統計
void
radixsort
(vector<
int>
& v)
int index =0;
for(
auto
& bucket: vc)
bucket.
clear()
;//}}
}
通排序思想是假定資料在[mi
n,ma
x][min, max]
[min,m
ax]之間均勻分布,將區間等分為n份,每份對應乙個桶。將資料新增到對應的桶中,然後桶內分別進行排序。最終,桶相對有序,桶內元素有序,整體有序
極端情況,直接令每個桶的大小為1.
各種排序演算法總結
注 以下所講排序,以公升序排序為例!選擇排序 作者思路 在一組數中,選擇第乙個數標記為最小值,在剩下的數中找比它小的數,若找到則交換兩數,標記新的 最小值 然後繼續往下找,這樣一趟下來就可以找到一組數中第二小的值,第二次以第二個數作為最小值,如此迴圈下去。這是最簡單 最基礎的一種排序演算法。例子 1...
各種排序演算法總結
1 插入排序 void insertsort int a,int n a j 1 key 插入排序是穩定的排序,平均和最壞時間複雜度是o n 2 最好的時間複雜度是o n 對應於全部排好序的情況。2 氣泡排序 void bubblesort int a,intn 氣泡排序是穩定的排序,平均和最壞時間...
各種排序演算法總結
created by vencent on 2008.8.29 1.插入排序 1.1 一般插入排序 insertsort int array,int length 1.2 折半插入排序 bininsertsort int array,int length 1.3 希爾排序 shellsort int...