一、排序分类
插入排序:
直接插入排序
折半插入排序
希尔排序
交换排序:
冒泡排序
快速排序
选择排序:
简单选择排序
堆排序
此文我们介绍选择排序,冒泡排序。
二、选择排序
时间复杂度:O(n²)
稳定性:不稳定,因为若第i个元素和另一元素交换,而其关键字大小相同的另一元素在前两者中间,可能导致相对位置改变。
选择排序的基本思想是:
每 i 趟排序都选出一个最小的元素,放在第 i 个位置上;
i 为正整数,由1依次递增到元素个数减1。
代码:
首先用模板写一个交换函数:
template<typename T>//声明一个模板
//typename可以替换成class
//告诉编译器后面代码中紧跟着的T不要报错,T是一个通用数据类型
void mySwap(T& a, T& b)
{
T temp = a;
a = b;
b = temp;
}
然后写选择排序:
template<typename T>
void mySort(T array[], int len)
{
for (int i = 0; i < len-1; i++)
{
int max = i;
for (int j = i + 1; j < len; j++)
{
if (array[max] < array[j])
{
max = j;
}
}
if (array[i] != array[max])
{
mySwap<int>(array[i], array[max]);
}
cout << "这是第" << i + 1 << "趟排序" << endl;
}
}
由于进行第len-1次排序后,第len次待排序元素只剩最后一个了,也就是说前len-1次排序已经将数组排成了有序数组,
所以写i<len-1即可。
测试代码:
int a[] = { 1,2,3,4 };
int len = sizeof(a) / sizeof(a[0]);
cout << len;
mySort(a, len);
for (int i = 0; i < len; i++)
{
cout << a[i] << endl;
}
运行截图:
三、冒泡排序
时间复杂度:O(n²)
稳定性:稳定,因为每一趟排序都会把一个元素放在最终位置上。那么关键字大小相同的两个元素,也会按照顺序依次放在最终位置上,不会“篡位”。
冒泡排序的思想是:从后往前(或者从前往后)两两比较相邻元素的值,若为逆序,则交换他们,直到序列比较完。我们称其为第一次冒泡,
结果是将最小的元素交换到待排序列的第一个位置。
每趟排序都把序列中最小的元素放到了序列的最终位置,
这样最多做n-1趟冒泡排序即可排好序。
放一张曾经写的冒泡排序思想:
这里改进一下,
外层:for(int i = 0;i<len-1;i++)
内层:for(int j = 0;j<len-1-i;j++)
代码:
template<typename T>
void myBubbleSort(T array[], int len)
{
for (int i = 0; i < len - 1; i++)
{
bool flag = false;
for (int j = 0; j < len - 1 - i; j++)
{
if (array[j] > array[j + 1])
{
mySwap<int>(array[j], array[j + 1]);
flag = true;
}
}
cout << "这是第" << i + 1 << "趟排序" << endl;
if (flag == false)
{
return;
}
}
记得使用flag!
因为交换排序会一一遍历,
所以使用flag可以让排序性能更好。
测试代码:
int a[] = { 4,3,2,1 };
int len = sizeof(a) / sizeof(a[0]);
myBubbleSort(a, len);
for (int i = 0; i < len; i++)
{
cout << a[i] << endl;
}
运行截图: