整理一下常见的排序算法。
- 插入排序
- 合并排序
- 冒泡排序
- 堆排序
- 快速排序
- 选择排序
插入排序
插入排序就是从前往后,逐个元素向自己前方插入,保持从0位到检索位的元素有序,直到遍历至最后一个元素。
C++实现:
void InsertSort(int* A, int n)
{
for (int i = 2;i < n;i++){
int curr = A[i];
int j = i-1;
while (j > 0&&A[j] > curr){
A[j+1] = A[j];
j--;
}
A[j+1] = curr;
}
}
算法复杂度:
合并排序
也叫归并排序,就是将要排序的数组分为多个子序列,让每个子序列有序,然后再把子序列合并。
C++实现:
void MergeSort(int* A, int begin, int end)
{
int size = end - begin + 1;
if (begin == end){
return;
}
int mid = begin + size / 2;
MergeSort(A, begin, mid-1);
MergeSort(A, mid, end);
int temp[size];
int j1 = begin;
int j2 = mid;
for (int i = 0;i < size;i++){
temp[i] = (j2 > end||(j1 < mid&&A[j1]<A[j2]))?A[j1++]:A[j2++];
}
for (int i = 0;i < size;i++){
A[begin+i] = temp[i];
}
}
算法时间复杂度:
冒泡排序
每个数字像是冒泡一样,慢慢地向上冒。每次遍历数组,检查当前位和后一位的大小,如果顺序不对,则交换位次。当一次遍历中没有发生交换,代表排序结束。
C++实现:
void BubbleSort(int* A, int n)
{
bool adjust = true;
while (adjust){
adjust = false;
for (int i = 0;i < n-1;i++){
if (A[i] > A[i+1]){
int temp = A[i];
A[i] = A[i+1];
A[i+1] = temp;
adjust = true;
}
}
}
}
算法时间复杂度:
堆排序
堆排序就是使用大根堆(或小根堆)进行排序。大根堆是一棵完全二叉树,每个父节点的值都不小于其两个子节点。大根堆使用数组进行存储,节点n的左节点为2n+1,右节点为左节点+1。排序过程为,首先把A[1-n]初始化为大根堆,然后把A[1](堆顶,最大的元素)与A[n]交换。然后再把A[1-(n-1)]维护为大根堆。重复至大根堆大小减为1.
C++实现:
void HeapSort(int* A, int n)
{
for (int i = n-1;i >= 0;i--){
MaxHeapify(A, n, i);
}
for (int i = n-1;i > 0;i--){
int temp = A[i];
A[i] = A[0];
A[0] = temp;
MaxHeapify(A, i, 0);
}
}
void MaxHeapify(int* A, int n, int pos)
{
int lchild = pos*2+1;
int rchild = lchild+1;
if (rchild < n){
if (A[pos] >= A[lchild]&&A[pos] >= A[rchild]){
return;
}
else if (A[lchild] >= A[rchild]){
int temp = A[pos];
A[pos] = A[lchild];
A[lchild] = temp;
MaxHeapify(A, n, lchild);
}
else {
int temp = A[pos];
A[pos] = A[rchild];
A[rchild] = temp;
MaxHeapify(A, n, rchild);
}
}
else if (lchild < n){
if (A[pos] <= A[lchild]){
int temp = A[pos];
A[pos] = A[lchild];
A[lchild] = temp;
MaxHeapify(A, n, lchild);
}
}
return;
}
算法时间复杂度:
快速排序
快排的思路是不断地通过一个基准值(通常是序列第一位)将序列分为比基准值大和比基准值小的两部分。然后再把子序列按同样方法处理,直到子序列大小为1.
C++实现:
void QuickSort(int* A, int begin, int end)
{
if (begin >= end){
return;
}
int l = begin+1, r = end;
while(l < r){
while(A[r]>=A[begin]&&l<r){
r--;
}
while(A[l]<A[begin]&&l<r){
l++;
}
swap(A[l], A[r]);
}
if (A[r] < A[begin]){
swap(A[r], A[begin]);
}
else {
r--;
}
QuickSort(A, begin, r-1);
QuickSort(A, r+1, end);
}
算法时间复杂度:
选择排序
选择排序就是每次从无序区遍历查出最小(大)的元素,放在有序区的末尾(首部)。(我感觉很脑残……)
C++实现:
void SelectSort(int* A, int n)
{
for (int i = 0;i < n-1;i++){
int min = A[i];
int min_pos = i;
for (int j = i+1;j < n;j++){
if (A[j] < min){
min_pos = j;
min = A[j];
}
}
swap(A[i], A[min_pos]);
}
}
算法时间复杂度: