1. 冒泡排序
1.1 算法原理
- 核心思想
多次遍历,每次遍历把两相邻数之间相比较,如果大数在前,小数在后,则交换。每次遍历后当前遍历区间内最大的元素会被放到区间的末尾。
- 算法过程
第一遍遍历区间为 [0, N-1],两个相邻元素进行比较,需使之维持较小元素在前,较大元素在后。遍历完后,数组中最大的元素会被放到数组的末尾位置,然后进行第二遍遍历。第二遍遍历区间为 [0, N-2],操作方法相同。遍历完后,数组中第二大的元素被会放到数组倒数二个位置,然后进行第三遍遍历。以此类推,直至遍历区间缩小到一个数或遍历一遍后都没有发生元素交换时,排序完成。
- 复杂度分析
时间复杂度 O(n^2),空间复杂度 O(1),为稳定排序。
1.2 实例
- 原数组为 [5, 3, 9, 1, 2]
- 第一遍遍历区间为 [0, 4],结果为 [3, 5, 1, 2, 9]
- 第二遍遍历区间为 [0, 3],结果为 [3, 1, 2, 5, 9]
- 第三遍遍历区间为 [0, 2],结果为 [1, 2, 3, 5, 9]
- 第四遍遍历区间为 [0, 1],结果为 [1, 2, 3, 5, 9]
1.3 示例程序
void Swap(int& x, int& y)
{
int tmp = x;
x = y;
y = tmp;
}
void BubbleSort(vector<int>& nums)
{
if (nums.size() < 2)
{
return;
}
bool changed = true; // 保证至少进行一遍比较
for (int i = 0; i < nums.size() && true == changed; i++)
{
changed = false;
for (int j = 0; j < nums.size() - i - 1; j++)
{
if (nums[j + 1] < nums[j])
{
Swap(nums[j + 1], nums[j])
changed = true;
}
}
}
}
2. 选择排序
2.1 算法原理
- 核心思想
多次遍历,每次遍历记录遍历区间内的最小元素,遍历后把最小元素放置到区间的开头。
- 算法过程
第一遍遍历区间为 [0, N-1],遍历过程记录最小值的元素及其下标。遍历完后,把最小值元素与数组首个元素交换,然后进行第二遍遍历。第二遍遍历区间为 [1, N-1],操作方法相同。遍历完后,把最小值元素与数组第二位置的元素交换,然后进行第三遍遍历。以此类推,直至遍历区间缩小到一个数时,排序完成。
- 复杂度分析
时间复杂度 O(n^2),空间复杂度 O(1),为非稳定排序。
2.2 实例
- 原数组为 [5, 3, 9, 1, 2]
- 第一遍遍历区间为 [0, 4],结果为 [1, 3, 9, 5, 2]
- 第二遍遍历区间为 [1, 4],结果为 [1, 2, 9, 5, 3]
- 第三遍遍历区间为 [2, 4],结果为 [1, 2, 3, 5, 9]
- 第四遍遍历区间为 [3, 4],结果为 [1, 2, 3, 5, 9]
2.3 示例程序
void Swap(int& x, int& y)
{
int tmp = x;
x = y;
y = tmp;
}
void SelectionSort(vector<int>& nums)
{
if (nums.size() < 2)
{
return;
}
for (int i = 0; i < nums.size() - 1; i++)
{
int min_index = i;
for (int j = i + 1; j < nums.size(); j++)
{
min_index = nums[min_index] > nums[j] ? j : min_index;
}
if (min_index != i)
{
Swap(nums[i], nums[min_index]);
}
}
}