1、冒泡排序 O(n2)
每一次把最大的移動到最右端,第一次從0~n-1中找到最大的放到n-1處,第二次從0~n-2中找到最大的放到n-2處……
class
BubbleSort
{
public
:
int
*
bubbleSort(
int
*
A,
int
n)
{
int
i,j,temp
=
0
;
for
(i
=
1
;i
< n;i++)
for
(j
=
0
;
j < n - i;j++) {
if
(A[j]
> A[j +
1
])
{
temp
= A[j +
1
];
A[j
+
1
]
= A[j];
A[j]
= temp;
}
}
return
A;
}
};
先把0處的看作最小值,從1~n-1中找到比它小的值,交換;再把1處的看作最小值,從2~n-1中找到比他小的,交換;……
class
SelectionSort
{
public
:
int
*
selectionSort(
int
*
A,
int
n)
{
if
(n
==
0
)
return
A;
int
i,j,min
=
0
,temp;
for
(i
=
0
;i
< n;i++) {
min
= i;
for
(j
= i+
1
;j
< n;j++) {
if
(A[j]
< A[min]) {
min
= j;
}
}
temp
= A[i];
A[i]
= A[min];
A[min]
= temp;
}
return
A;
}
};
3、插入排序 O(n2)
先把0處看作已排序的序列,將1~n-1處逐個地與0處比較,若比0處小,則將其插入到已排序的序列中;……;假設0~3已排序,將4~n-1處依次與3處比較,若小於3處,則將其插入到0~3的適當位置;……
class
InsertionSort
{
public
:
int
*
insertionSort(
int
*
A,
int
n)
{
int
i,j,k,temp;
for
(i
=
1
;i
< n;i++) {
k
= i;
for
(j
= i-
1
;j
>=
0
;j--)
{
if
(A[k]
< A[j]) {
temp
= A[k];
A[k]
= A[j];
A[j]
= temp;
k
= j;
}
}
}
return
A;
}
};
4、歸併排序(遞歸) O(NlogN)
先將序列分成2個子序列,再分成4個,……,直到所有子序列都只含一個元素;對每個子序列排序,再將相鄰的兩個已排序子序列歸併爲一個排序序列,依次類推,最後歸併出原序列的排序序列。
class
MergeSort
{
public
:
void
Merge(
int
*
A,
int
start,
int
middle,
int
end)
{
int
temp[end-start
+
1
];
int
k
=
0
;
for
(
int
i
= start,j = middle +
1
;i
<= middle || j <= end;k++) {
if
(i
<= middle && j <= end) {
if
(A[i]
< A[j]) {
temp[k]
= A[i];
i++;
}
else
{
temp[k]
= A[j];
j++;
}
}
else
if
(i
<= middle) {
temp[k]
= A[i];
i++;
}
else
{
temp[k]
= A[j];
j++;
}
}
for
(
int
m
=
0
;m
< k;m++)
A[start
+ m] = temp[m];
}
void
Divide(
int
*
A,
int
start,
int
end)
{
if
(start
< end) {
int
m
= (start + end)/
2
;
Divide(A,start,m);
Divide(A,m+
1
,end);
Merge(A,start,m,end);
}
}
int
*
mergeSort(
int
*
A,
int
n)
{
Divide(A,
0
,n-
1
);
return
A;
}
};
5、快速排序(遞歸) O(NlogN)
先從序列中選取一個元素爲基數,一般選最左邊一個;兩個指針i、j分別從序列的頭尾向中間遍歷;j從右到左找到小於基數的元素(j處),複製到基數處(i處),i++;然後i從左向右找到大於基數的元素(i處),複製到j處,j--;依次類推,直到i與j相遇使i>=j,while循環結束,此時已把序列分成左右兩個子序列,左邊小於基數,右邊大於基數;再將左右子序列當做未排序序列進行遞歸。
class QuickSort {
public:
void Quick(int* A,int start,int end) {
if (start >= end) return;
else {
int i = start,j = end;
int base = A[i];
while (i < j) {
while (i < j && A[j] > base) j--;
if (i < j) {
A[i] = A[j];
i++;
}
while (i < j && A[i] < base) i++;
if (i < j) {
A[j] = A[i];
j--;
}
}
A[i] = base;
Quick(A,start,i - 1);
Quick(A,i + 1,end);
}
}
int* quickSort(int* A, int n) {
// write code here
Quick(A,0,n-1);
return A;
}
};
6、堆排序 O(NlogN)
堆實際上是一種思想,不是一種數據存儲結構,堆中數據的邏輯結構與完全二叉樹一樣,設總共有n個結點,則葉結點個數爲n+1/2或者n/2,則非葉子結點個數爲n-1/2或者n/2,當n能被2整除時爲n/2,不能被整除時爲n-1/2。
思路:
(1)堆化數組。給定一個長度爲n的亂序數組,若要遞增排序,則先將其堆化(按層序存儲),即把原數組調整爲大端堆。
(2)取堆頂元素放入數組末尾。每次將堆頂元素與數組末尾元素交換。
(3)調整交換元素後的堆。再從堆頂到第n-2個元素調整數組爲大端堆,直到n-2=1爲止,即堆中只剩下一個元素未放入排序序列爲止。
class
HeapSort
{
public
:
void
heapify(
int
*
A,
int
i,
int
n)
{
int
j,temp;
temp
= A[i];
j
=
2
*i
+
1
;
while
(j
< n) {
if
(j
+
1
<
n && A[j+
1
]
> A[j]) j++;
if
(A[j]
<= temp)
break
;
A[i]
= A[j];
i
= j;
j
=
2
*i
+
1
;
}
A[i]
= temp;
return
;
}
int
*
heapSort(
int
*
A,
int
n)
{
//
write code here
int
temp;
for
(
int
m
= n/
2
-
1
;m
>=
0
;m--)
heapify(A,m,n);
for
(
int
k
= n-
1
;k
>=
1
;k--)
{
temp
= A[k];
A[k]
= A[
0
];
A[
0
]
= temp;
heapify(A,
0
,k);
}
return
A;
}
};
7、希爾排序 O(NlogN)
插入排序的改進。每一次比較的步長是變化的。例如,長度爲n的數組,第一次設置步長爲n/2,認爲前n/2個數已經排序,從第n/2+1個開始,將其逐個與第1個、2個……比較,大於則交換,小於則不做操作。然後減小步長,繼續以上步驟直到步長變爲1.
class
ShellSort
{
public
:
int
*
shellSort(
int
*
A,
int
n)
{
//
write code here
int
span
= n/
2
;
int
i,j,temp;
while
(span
>=
1
)
{
for
(i
= span;i < n;i++) {
j
= i - span;
while
(j
>=
0
)
{
if
(A[j]
> A[i]) {
temp
= A[j];
A[j]
= A[i];
A[i]
= temp;
}
j
-= span;
}
}
span--;
}
return
A;
}
};
8、計數排序 O(N)
(1)先確認待排序數組A元素的取值範圍,相當於找出最大值max和最小值min,桶C的大小必須要能包含所有的元素。
(2)順序遍歷數組A,把A[i]與桶C的下標對應起來,即,將C[A[i]-min]加1。這樣A最小的元素與C的第一個下標對應,最大元素與C的最後一個下標對應。這個過程相當於把A中元素裝入對應的桶中。
(3)順序遍歷桶C,把桶中元素按順序倒出來,就是從小到大的已排序序列。
class
CountingSort
{
public
:
int
*
countingSort(
int
*
A,
int
n)
{
//
write code here
int
max
= A[
0
],min
= A[
0
];
for
(
int
i
=
0
;i
< n;i++) {
if
(A[i]
> max) max = A[i];
if
(A[i]
< min) min = A[i];
}
int
sizeC
= max - min +
1
;
int
*C
=
new
int
[sizeC];
for
(
int
i
=
0
;i
< sizeC;i++)
C[i]
=
0
;
for
(
int
j
=
0
;j
< n;j++) {
C[A[j]-min]++;
}
int
z
=
0
;
for
(
int
m
=
0
;m
< sizeC;m++) {
while
(C[m]
>
0
)
{
A[z]
= m + min;
z++;
C[m]--;
}
}
delete
[]C;
return
A;
}
};
9、基數排序 O(N)
先根據個位把各元素入桶,把桶中元素倒出來得到按個位排序的序列;再按照十位把各元素入桶,倒出來得到按十位排序的序列;以此類推……
注:A中數據小於2000.
一維數組實現:
class
RadixSort
{
public
:
int
*
radixSort(
int
*
A,
int
n)
{
//
write code here
int
C[
10
];
int
divisor[
5
]
= {
1
,
10
,
100
,
1000
,
10000
};
int
*B
=
new
int
[n];
for
(
int
i
=
0
;i
<
4
;i++)
{
for
(
int
j
=
0
;j
<
10
;j++)
C[j]
=
0
;
for
(
int
k
=
0
;k
< n;k++) {
int
unit
= (A[k]%divisor[i+
1
])/divisor[i];
C[unit]++;
}
for
(
int
j
=
1
;j
<
10
;j++)
C[j]
+= C[j-
1
];
for
(
int
k
= n-
1
;k
>=
0
;k--)
{
int
unit
= (A[k]%divisor[i+
1
])/divisor[i];
B[C[unit]-
1
]
= A[k];
C[unit]--;
}
for
(
int
j
=
0
;j
< n;j++)
A[j]
= B[j];
}
delete
[]B;
B
= NULL;
return
A;
}
};
二維數組實現:
class RadixSort {
int* radixSort(int* A, int n) {
// write code here
vector<deque<int> > bucket(10);
int divisor[] = {1,10,100,1000,10000};
for (int i = 0;i < 4;i++) {
for (int j = 0;j < n;j++) {
int unit = (A[j]%divisor[i+1])/divisor[i];
bucket[unit].push_back(A[j]);
}
for (int j = 0, k = 0;j < 10;j++) {
while (!bucket[j].empty()) {
A[k++] = bucket[j].front();
bucket[j].pop_front();
}
}
}
return A;