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;