冒泡排序及优化,参考匈牙利冒泡排序舞蹈
//冒泡递归写法
void f0(int a[], int len)
{
if (len > 1)
{
int Loop = 0;
for (int i = 0; i < len - 1; i++)
{
Loop++;
if (a[i] > a[i + 1])
{
swap(a[i], a[i + 1]);
Loop = 0;
}
}
f0(a, len - 1 - Loop);
}
}
//循环写法
void f1(int a[], int len)
{
for (int i = len - 1; i >= 0; i--)
{
int Loop = 0;
for (int j = 0; j < i; j++)
{
if (a[j] > a[j + 1])
{
swap(a[j], a[j + 1]);
Loop = 0;
}
else
{
Loop++;
}
}
i -= Loop;
}
}
选择排序,每一趟把最大或者最小的元素放到最后
//递归
void f2(int a[], int len)
{
if (len > 1)
{
int max = a[0];
int index = 0;
for (int i = 0; i < len; i++)
{
if (a[i] > max)
{
index = i;
max = a[i];
}
}
swap(a[index], a[len - 1]);
f2(a, len - 1);
}
}
//循环
void f3(int a[], int len)
{
for (int i = len - 1; i >= 0; i--)
{
int max = a[0];
int index = 0;
for (int j = 0; j <= i; j++)
{
if (a[j] > max)
{
index = j;
max = a[j];
}
}
swap(a[i], a[index]);
}
}
插入排序,将前面的n个数视为已排好序,然后将第n+1个数插入到前面的正确位置
//递归
void f4(int a[], int sorted, int len)
{
if (len != sorted + 1)
{
for (int i = sorted + 1; i >= 1 && a[i] < a[i - 1]; i--)
{
swap(a[i], a[i - 1]);
}
f4(a, sorted + 1, len);
}
}
//循环
void f5(int a[], int len)
{
for (int i = 1; i < len; i++)
{
for (int j = i; j >= 1 && a[j] < a[j - 1]; j--)
{
swap(a[j], a[j - 1]);
}
}
}
归并排序,将两端已排好序的序列合并,优化见另一篇博文
void f6(int a[], int len)
{
if (len > 1)
{
f6(a, len / 2);
f6(a + len / 2, len - len / 2);
int b[len];
int cnt = 0;
int start1 = 0, end1 = len / 2;
int start2 = len / 2, end2 = len;
while (start1 < end1 && start2 < end2)
{
if (a[start1] < a[start2])
{
b[cnt++] = a[start1++];
}
else
{
b[cnt++] = a[start2++];
}
}
while (start1 < end1)
{
b[cnt++] = a[start1++];
}
while (start2 < end2)
{
b[cnt++] = a[start2++];
}
for (int i = 0; i < len; i++)
{
a[i] = b[i];
}
}
}
快速排序,以第1个数为参照,找到其正确位置,且让其前面的数比参照小,后面的数比参照大
//快排
void f7(int a[], int len)
{
if (len > 1)
{
int key = a[0];
int l = 0, r = len - 1;
while (l < r)
{
while (l < r && a[r] > key)
{
r--;
}
a[l] = a[r];
while (l < r && a[l] < key)
{
l++;
}
a[r] = a[l];
}
a[l] = key;
f7(a, l);
f7(a + l + 1, len - 1 - l);
}
}
堆排序,首先建堆,从最后一个叶子节点开始,往前修正,建堆后最大的元素在堆顶。交换堆顶与最后一个元素,len--,修正堆顶
//修正堆中索引为index的元素
void update_heap(int a[], int index, int len)
{
while (index * 2 < len)
{
int ch = 2 * index;
if (ch + 1 < len && a[ch + 1] > a[ch])
{
ch++;
}
if (a[ch] > a[index])
{
swap(a[ch], a[index]);
index = ch;
}
else
{
break;
}
}
}
//建堆,交换,修正
void f8(int a[], int len)
{
for (int i = len / 2 - 1; i >= 0; i--)
{
update_heap(a, i, len);
}
for (int i = len - 1; i >= 1; i--)
{
swap(a[i], a[0]);
update_heap(a, 0, i);
}
}
基数排序:按照个位数依次进队,然后出队放回数组,按照十位数依次进队,然后出队放回数组...
//基数排序
void f9(int a[], int len)
{
queue<int> q[10];
int q0_size = 0;
int m = 1;
while (q0_size != len)
{
for (int i = 0; i < len; i++)
{
int digit = (a[i] / m) % 10;
q[digit].push(a[i]);
}
q0_size = (int)q[0].size();
int cnt = 0;
for (int i = 0; i < 10; i++)
{
while (!q[i].empty())
{
int temp = q[i].front();
q[i].pop();
a[cnt++] = temp;
}
}
m *= 10;
}
}
希尔排序:增量缩小的插入排序
//希尔排序
void f10(int a[], int len)
{
for (int gap = len / 2; gap > 0; gap /= 2)
{
for (int j = gap; j < len; j++)
{
for (int i = j; i - gap >= 0 && a[i] < a[i - gap]; i -= gap)
{
swap(a[i], a[i - gap]);
}
}
}
}
main函数
int main()
{
int a[10] = {4, 2, 5, 6, 1, 0, 3, 7, 8, 9};
f0(a, 10);
for (int i = 0; i < 10; i++)
{
printf("%d ", a[i]);
}
putchar(10);
return 0;
}
前三种简单排序:O(n^2),选择排序不稳定,其它稳定
中间三种好的排序:O(nlogn), 归并排序稳定,其它不稳定
最后两种,希尔不稳定,基数稳定